summary refs log tree commit diff stats
path: root/exec.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-10-24 19:37:33 +0100
committerPeter Maydell <peter.maydell@linaro.org>2016-10-24 19:37:34 +0100
commitfe4c04071f702e008da7db06d0a220b27e1ab3ac (patch)
tree97c3699d2cd15ec48436d53218178b903389f6e3 /exec.c
parent45b567d645c22fb79f4698a13396718084f7cf72 (diff)
parentcc083d8a25e0a886c3cd4bea0bf57ac4e896fa3f (diff)
downloadfocaccia-qemu-fe4c04071f702e008da7db06d0a220b27e1ab3ac.tar.gz
focaccia-qemu-fe4c04071f702e008da7db06d0a220b27e1ab3ac.zip
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20161024' into staging
target-arm queue:
 * support variable (runtime-determined) page sizes, for a
   nearly-20% speedup of TCG for ARMv7 and v8 CPUs with 4K pages
 * ptimer: add tests, support more flexible behaviour around
   what happens on the "zero" tick, use ptimer for a9gtimer
 * virt: ACPI: Add IORT Structure definition
 * i2c: Fix SMBus read transactions to avoid double events
 * timer: stm32f2xx_timer: add check for prescaler value
 * QOMify musicpal, pxa2xx_gpio, strongarm, pl110
 * target-arm: Implement new HLT trap for semihosting
 * i2c: Add asserts for second smbus i2c_start_transfer()

# gpg: Signature made Mon 24 Oct 2016 18:24:17 BST
# gpg:                using RSA key 0x3C2525ED14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>"
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20161024: (32 commits)
  i2c: Add asserts for second smbus i2c_start_transfer()
  target-arm: Implement new HLT trap for semihosting
  hw/display: QOM'ify pl110.c
  hw/arm: QOM'ify strongarm.c
  hw/arm: QOM'ify pxa2xx_gpio.c
  hw/arm: QOM'ify musicpal.c
  timer: stm32f2xx_timer: add check for prescaler value
  i2c: Fix SMBus read transactions to avoid double events
  timer: a9gtimer: remove loop to auto-increment comparator
  ARM: Virt: ACPI: Build an IORT table with RC and ITS nodes
  ACPI: Add IORT Structure definition
  tests: Add tests for the ARM MPTimer
  arm_mptimer: Convert to use ptimer
  tests: ptimer: Replace 10000 with 1
  tests: ptimer: Change the copyright comment
  tests: ptimer: Add tests for "no counter round down" policy
  hw/ptimer: Add "no counter round down" policy
  tests: ptimer: Add tests for "no immediate reload" policy
  hw/ptimer: Add "no immediate reload" policy
  tests: ptimer: Add tests for "no immediate trigger" policy
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'exec.c')
-rw-r--r--exec.c47
1 files changed, 44 insertions, 3 deletions
diff --git a/exec.c b/exec.c
index 6d7f600c0c..963b91a018 100644
--- a/exec.c
+++ b/exec.c
@@ -93,6 +93,11 @@ static MemoryRegion io_mem_unassigned;
 
 #endif
 
+#ifdef TARGET_PAGE_BITS_VARY
+int target_page_bits;
+bool target_page_bits_decided;
+#endif
+
 struct CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus);
 /* current CPU in the current thread. It is only valid inside
    cpu_exec() */
@@ -102,8 +107,37 @@ __thread CPUState *current_cpu;
    2 = Adaptive rate instruction counting.  */
 int use_icount;
 
+bool set_preferred_target_page_bits(int bits)
+{
+    /* The target page size is the lowest common denominator for all
+     * the CPUs in the system, so we can only make it smaller, never
+     * larger. And we can't make it smaller once we've committed to
+     * a particular size.
+     */
+#ifdef TARGET_PAGE_BITS_VARY
+    assert(bits >= TARGET_PAGE_BITS_MIN);
+    if (target_page_bits == 0 || target_page_bits > bits) {
+        if (target_page_bits_decided) {
+            return false;
+        }
+        target_page_bits = bits;
+    }
+#endif
+    return true;
+}
+
 #if !defined(CONFIG_USER_ONLY)
 
+static void finalize_target_page_bits(void)
+{
+#ifdef TARGET_PAGE_BITS_VARY
+    if (target_page_bits == 0) {
+        target_page_bits = TARGET_PAGE_BITS_MIN;
+    }
+    target_page_bits_decided = true;
+#endif
+}
+
 typedef struct PhysPageEntry PhysPageEntry;
 
 struct PhysPageEntry {
@@ -153,7 +187,7 @@ typedef struct subpage_t {
     MemoryRegion iomem;
     AddressSpace *as;
     hwaddr base;
-    uint16_t sub_section[TARGET_PAGE_SIZE];
+    uint16_t sub_section[];
 } subpage_t;
 
 #define PHYS_SECTION_UNASSIGNED 0
@@ -2215,8 +2249,7 @@ static subpage_t *subpage_init(AddressSpace *as, hwaddr base)
 {
     subpage_t *mmio;
 
-    mmio = g_malloc0(sizeof(subpage_t));
-
+    mmio = g_malloc0(sizeof(subpage_t) + TARGET_PAGE_SIZE * sizeof(uint16_t));
     mmio->as = as;
     mmio->base = base;
     memory_region_init_io(&mmio->iomem, NULL, &subpage_ops, mmio,
@@ -2808,6 +2841,14 @@ void cpu_register_map_client(QEMUBH *bh)
 void cpu_exec_init_all(void)
 {
     qemu_mutex_init(&ram_list.mutex);
+    /* The data structures we set up here depend on knowing the page size,
+     * so no more changes can be made after this point.
+     * In an ideal world, nothing we did before we had finished the
+     * machine setup would care about the target page size, and we could
+     * do this much later, rather than requiring board models to state
+     * up front what their requirements are.
+     */
+    finalize_target_page_bits();
     io_mem_init();
     memory_map_init();
     qemu_mutex_init(&map_client_list_lock);