diff options
author | Peter Maydell | 2016-10-24 20:37:33 +0200 |
---|---|---|
committer | Peter Maydell | 2016-10-24 20:37:34 +0200 |
commit | fe4c04071f702e008da7db06d0a220b27e1ab3ac (patch) | |
tree | 97c3699d2cd15ec48436d53218178b903389f6e3 /translate-all.c | |
parent | Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (diff) | |
parent | i2c: Add asserts for second smbus i2c_start_transfer() (diff) | |
download | qemu-fe4c04071f702e008da7db06d0a220b27e1ab3ac.tar.gz qemu-fe4c04071f702e008da7db06d0a220b27e1ab3ac.tar.xz 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 'translate-all.c')
-rw-r--r-- | translate-all.c | 71 |
1 files changed, 46 insertions, 25 deletions
diff --git a/translate-all.c b/translate-all.c index 8ca393c9d0..86b45a19c5 100644 --- a/translate-all.c +++ b/translate-all.c @@ -97,25 +97,24 @@ typedef struct PageDesc { #define V_L2_BITS 10 #define V_L2_SIZE (1 << V_L2_BITS) -/* The bits remaining after N lower levels of page tables. */ -#define V_L1_BITS_REM \ - ((L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS) % V_L2_BITS) - -#if V_L1_BITS_REM < 4 -#define V_L1_BITS (V_L1_BITS_REM + V_L2_BITS) -#else -#define V_L1_BITS V_L1_BITS_REM -#endif - -#define V_L1_SIZE ((target_ulong)1 << V_L1_BITS) - -#define V_L1_SHIFT (L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS - V_L1_BITS) - uintptr_t qemu_host_page_size; intptr_t qemu_host_page_mask; -/* The bottom level has pointers to PageDesc */ -static void *l1_map[V_L1_SIZE]; +/* + * L1 Mapping properties + */ +static int v_l1_size; +static int v_l1_shift; +static int v_l2_levels; + +/* The bottom level has pointers to PageDesc, and is indexed by + * anything from 4 to (V_L2_BITS + 3) bits, depending on target page size. + */ +#define V_L1_MIN_BITS 4 +#define V_L1_MAX_BITS (V_L2_BITS + 3) +#define V_L1_MAX_SIZE (1 << V_L1_MAX_BITS) + +static void *l1_map[V_L1_MAX_SIZE]; /* code generation context */ TCGContext tcg_ctx; @@ -125,6 +124,26 @@ TCGContext tcg_ctx; __thread int have_tb_lock; #endif +static void page_table_config_init(void) +{ + uint32_t v_l1_bits; + + assert(TARGET_PAGE_BITS); + /* The bits remaining after N lower levels of page tables. */ + v_l1_bits = (L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS) % V_L2_BITS; + if (v_l1_bits < V_L1_MIN_BITS) { + v_l1_bits += V_L2_BITS; + } + + v_l1_size = 1 << v_l1_bits; + v_l1_shift = L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS - v_l1_bits; + v_l2_levels = v_l1_shift / V_L2_BITS - 1; + + assert(v_l1_bits <= V_L1_MAX_BITS); + assert(v_l1_shift % V_L2_BITS == 0); + assert(v_l2_levels >= 0); +} + void tb_lock(void) { #ifdef CONFIG_USER_ONLY @@ -332,6 +351,8 @@ void page_size_init(void) static void page_init(void) { page_size_init(); + page_table_config_init(); + #if defined(CONFIG_BSD) && defined(CONFIG_USER_ONLY) { #ifdef HAVE_KINFO_GETVMMAP @@ -408,10 +429,10 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc) int i; /* Level 1. Always allocated. */ - lp = l1_map + ((index >> V_L1_SHIFT) & (V_L1_SIZE - 1)); + lp = l1_map + ((index >> v_l1_shift) & (v_l1_size - 1)); /* Level 2..N-1. */ - for (i = V_L1_SHIFT / V_L2_BITS - 1; i > 0; i--) { + for (i = v_l2_levels; i > 0; i--) { void **p = atomic_rcu_read(lp); if (p == NULL) { @@ -826,10 +847,10 @@ static void page_flush_tb_1(int level, void **lp) static void page_flush_tb(void) { - int i; + int i, l1_sz = v_l1_size; - for (i = 0; i < V_L1_SIZE; i++) { - page_flush_tb_1(V_L1_SHIFT / V_L2_BITS - 1, l1_map + i); + for (i = 0; i < l1_sz; i++) { + page_flush_tb_1(v_l2_levels, l1_map + i); } } @@ -1883,16 +1904,16 @@ static int walk_memory_regions_1(struct walk_memory_regions_data *data, int walk_memory_regions(void *priv, walk_memory_regions_fn fn) { struct walk_memory_regions_data data; - uintptr_t i; + uintptr_t i, l1_sz = v_l1_size; data.fn = fn; data.priv = priv; data.start = -1u; data.prot = 0; - for (i = 0; i < V_L1_SIZE; i++) { - int rc = walk_memory_regions_1(&data, (target_ulong)i << (V_L1_SHIFT + TARGET_PAGE_BITS), - V_L1_SHIFT / V_L2_BITS - 1, l1_map + i); + for (i = 0; i < l1_sz; i++) { + target_ulong base = i << (v_l1_shift + TARGET_PAGE_BITS); + int rc = walk_memory_regions_1(&data, base, v_l2_levels, l1_map + i); if (rc != 0) { return rc; } |