:p
atchew
Login
The big thing in here is RTH's caching-of-tb-flags patchset which should improve TCG performance. thanks -- PMM The following changes since commit 2152e740a8938b3bad73bfe1a01f8b94dab02d41: Merge remote-tracking branch 'remotes/vivier2/tags/trivial-branch-pull-request' into staging (2019-10-22 12:03:03 +0100) are available in the Git repository at: https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20191022 for you to fetch changes up to 833043a060f7d0e95ded88e61e992466305c0345: hw/arm/digic4: Inline digic4_board_setup_ram() function (2019-10-22 14:21:57 +0100) ---------------------------------------------------------------- target-arm queue: * Fix sign-extension for SMLAL* instructions * aspeed: Add an AST2600 eval board * Various ptimer device conversions to new transaction API * Cache TB flags to avoid expensively recomputing them every time * Add a dummy Samsung SDHCI controller model to exynos4 boards * Minor refactorings of RAM creation for some arm boards ---------------------------------------------------------------- Cédric Le Goater (1): aspeed: Add an AST2600 eval board Guenter Roeck (1): hw/timer/exynos4210_mct: Initialize ptimer before starting it Peter Maydell (7): hw/timer/arm_mptimer.c: Undo accidental rename of arm_mptimer_init() hw/timer/puv3_ost.c: Switch to transaction-based ptimer API hw/timer/sh_timer: Switch to transaction-based ptimer API hw/timer/lm32_timer: Switch to transaction-based ptimer API hw/timer/altera_timer.c: Switch to transaction-based ptimer API hw/watchdog/etraxfs_timer.c: Switch to transaction-based ptimer API hw/m68k/mcf5208.c: Switch to transaction-based ptimer API Philippe Mathieu-Daudé (9): hw/sd/sdhci: Add a comment to distinct the i.MX eSDHC functions hw/sd/sdhci: Add dummy Samsung SDHCI controller hw/arm/exynos4210: Use the Samsung s3c SDHCI controller hw/arm/xilinx_zynq: Use the IEC binary prefix definitions hw/arm/mps2: Use the IEC binary prefix definitions hw/arm/collie: Create the RAM in the board hw/arm/omap2: Create the RAM in the board hw/arm/omap1: Create the RAM in the board hw/arm/digic4: Inline digic4_board_setup_ram() function Richard Henderson (23): target/arm: Fix sign-extension for SMLAL* target/arm: Split out rebuild_hflags_common target/arm: Split out rebuild_hflags_a64 target/arm: Split out rebuild_hflags_common_32 target/arm: Split arm_cpu_data_is_big_endian target/arm: Split out rebuild_hflags_m32 target/arm: Reduce tests vs M-profile in cpu_get_tb_cpu_state target/arm: Split out rebuild_hflags_a32 target/arm: Split out rebuild_hflags_aprofile target/arm: Hoist XSCALE_CPAR, VECLEN, VECSTRIDE in cpu_get_tb_cpu_state target/arm: Simplify set of PSTATE_SS in cpu_get_tb_cpu_state target/arm: Hoist computation of TBFLAG_A32.VFPEN target/arm: Add arm_rebuild_hflags target/arm: Split out arm_mmu_idx_el target/arm: Hoist store to cs_base in cpu_get_tb_cpu_state target/arm: Add HELPER(rebuild_hflags_{a32, a64, m32}) target/arm: Rebuild hflags at EL changes target/arm: Rebuild hflags at MSR writes target/arm: Rebuild hflags at CPSR writes target/arm: Rebuild hflags at Xscale SCTLR writes target/arm: Rebuild hflags for M-profile target/arm: Rebuild hflags for M-profile NVIC target/arm: Rely on hflags correct in cpu_get_tb_cpu_state hw/arm/strongarm.h | 4 +- include/hw/arm/aspeed.h | 1 + include/hw/arm/omap.h | 10 +- include/hw/sd/sdhci.h | 2 + target/arm/cpu.h | 84 ++++++---- target/arm/helper.h | 4 + target/arm/internals.h | 9 ++ hw/arm/aspeed.c | 23 +++ hw/arm/collie.c | 8 +- hw/arm/digic_boards.c | 9 +- hw/arm/exynos4210.c | 2 +- hw/arm/mps2-tz.c | 3 +- hw/arm/mps2.c | 3 +- hw/arm/nseries.c | 10 +- hw/arm/omap1.c | 12 +- hw/arm/omap2.c | 13 +- hw/arm/omap_sx1.c | 8 +- hw/arm/palm.c | 8 +- hw/arm/strongarm.c | 7 +- hw/arm/xilinx_zynq.c | 3 +- hw/intc/armv7m_nvic.c | 22 +-- hw/m68k/mcf5208.c | 9 +- hw/sd/sdhci.c | 68 +++++++- hw/timer/altera_timer.c | 13 +- hw/timer/arm_mptimer.c | 4 +- hw/timer/etraxfs_timer.c | 23 +-- hw/timer/exynos4210_mct.c | 2 +- hw/timer/lm32_timer.c | 13 +- hw/timer/puv3_ost.c | 9 +- hw/timer/sh_timer.c | 13 +- linux-user/syscall.c | 1 + target/arm/cpu.c | 1 + target/arm/helper-a64.c | 3 + target/arm/helper.c | 393 +++++++++++++++++++++++++++++---------------- target/arm/m_helper.c | 6 + target/arm/machine.c | 1 + target/arm/op_helper.c | 4 + target/arm/translate-a64.c | 13 +- target/arm/translate.c | 37 ++++- 39 files changed, 588 insertions(+), 270 deletions(-)
From: Richard Henderson <richard.henderson@linaro.org> The 32-bit product should be sign-extended, not zero-extended. Fixes: ea96b374641b Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com> Message-id: 20190912183058.17947-1-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/translate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target/arm/translate.c b/target/arm/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -XXX,XX +XXX,XX @@ static bool op_smlaxxx(DisasContext *s, arg_rrrr *a, case 2: tl = load_reg(s, a->ra); th = load_reg(s, a->rd); - t1 = tcg_const_i32(0); + /* Sign-extend the 32-bit product to 64 bits. */ + t1 = tcg_temp_new_i32(); + tcg_gen_sari_i32(t1, t0, 31); tcg_gen_add2_i32(tl, th, tl, th, t0, t1); tcg_temp_free_i32(t0); tcg_temp_free_i32(t1); -- 2.20.1
From: Cédric Le Goater <clg@kaod.org> Define the board with 1 GiB of RAM but some boards can have up to 2 GiB. Signed-off-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: Joel Stanley <joel@jms.id.au> Message-id: 20191016090745.15334-1-clg@kaod.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- include/hw/arm/aspeed.h | 1 + hw/arm/aspeed.c | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/hw/arm/aspeed.h b/include/hw/arm/aspeed.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed.h +++ b/include/hw/arm/aspeed.h @@ -XXX,XX +XXX,XX @@ typedef struct AspeedBoardConfig { const char *desc; const char *soc_name; uint32_t hw_strap1; + uint32_t hw_strap2; const char *fmc_model; const char *spi_model; uint32_t num_cs; diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -XXX,XX +XXX,XX @@ struct AspeedBoardState { /* Witherspoon hardware value: 0xF10AD216 (but use romulus definition) */ #define WITHERSPOON_BMC_HW_STRAP1 ROMULUS_BMC_HW_STRAP1 +/* AST2600 evb hardware value */ +#define AST2600_EVB_HW_STRAP1 0x000000C0 +#define AST2600_EVB_HW_STRAP2 0x00000003 + /* * The max ram region is for firmwares that scan the address space * with load/store to guess how much RAM the SoC has. @@ -XXX,XX +XXX,XX @@ static void aspeed_board_init(MachineState *machine, &error_abort); object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap1, "hw-strap1", &error_abort); + object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap2, "hw-strap2", + &error_abort); object_property_set_int(OBJECT(&bmc->soc), cfg->num_cs, "num-cs", &error_abort); object_property_set_int(OBJECT(&bmc->soc), machine->smp.cpus, "num-cpus", @@ -XXX,XX +XXX,XX @@ static void ast2500_evb_i2c_init(AspeedBoardState *bmc) i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 0x32); } +static void ast2600_evb_i2c_init(AspeedBoardState *bmc) +{ + /* Start with some devices on our I2C busses */ + ast2500_evb_i2c_init(bmc); +} + static void romulus_bmc_i2c_init(AspeedBoardState *bmc) { AspeedSoCState *soc = &bmc->soc; @@ -XXX,XX +XXX,XX @@ static const AspeedBoardConfig aspeed_boards[] = { .num_cs = 2, .i2c_init = witherspoon_bmc_i2c_init, .ram = 512 * MiB, + }, { + .name = MACHINE_TYPE_NAME("ast2600-evb"), + .desc = "Aspeed AST2600 EVB (Cortex A7)", + .soc_name = "ast2600-a0", + .hw_strap1 = AST2600_EVB_HW_STRAP1, + .hw_strap2 = AST2600_EVB_HW_STRAP2, + .fmc_model = "w25q512jv", + .spi_model = "mx66u51235f", + .num_cs = 1, + .i2c_init = ast2600_evb_i2c_init, + .ram = 1 * GiB, }, }; -- 2.20.1
From: Guenter Roeck <linux@roeck-us.net> When booting a recent Linux kernel, the qemu message "Timer with delta zero, disabling" is seen, apparently because a ptimer is started before being initialized. Fix the problem by initializing the offending ptimer before starting it. The bug is effectively harmless in the old QEMUBH setup because the sequence of events is: * the delta zero means the timer expires immediately * ptimer_reload() arranges for exynos4210_gfrc_event() to be called * ptimer_reload() notices the zero delta and disables the timer * later, the QEMUBH runs, and exynos4210_gfrc_event() correctly configures the timer and restarts it In the new transaction based API the bug is still harmless, but differences of when the callback function runs mean the message is not printed any more: * ptimer_run() does nothing as it's inside a transaction block * ptimer_transaction_commit() sees it has work to do and calls ptimer_reload() * the zero delta means the timer expires immediately * ptimer_reload() calls exynos4210_gfrc_event() directly * exynos4210_gfrc_event() configures the timer * the delta is no longer zero so ptimer_reload() doesn't complain (the zero-delta test is after the trigger-callback in the ptimer_reload() function) Regardless, the behaviour here was not intentional, and we should just program the ptimer correctly to start with. Signed-off-by: Guenter Roeck <linux@roeck-us.net> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20191018143149.9216-1-peter.maydell@linaro.org [PMM: Expansion/clarification of the commit message: the message is about a zero delta, not a zero period; added detail to the commit message of the analysis of what is happening and why the kernel boots even with the message; added note that the message goes away with the new ptimer API] Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/timer/exynos4210_mct.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c index XXXXXXX..XXXXXXX 100644 --- a/hw/timer/exynos4210_mct.c +++ b/hw/timer/exynos4210_mct.c @@ -XXX,XX +XXX,XX @@ static void exynos4210_mct_write(void *opaque, hwaddr offset, /* Start FRC if transition from disabled to enabled */ if ((value & G_TCON_TIMER_ENABLE) > (old_val & G_TCON_TIMER_ENABLE)) { - exynos4210_gfrc_start(&s->g_timer); + exynos4210_gfrc_restart(s); } if ((value & G_TCON_TIMER_ENABLE) < (old_val & G_TCON_TIMER_ENABLE)) { -- 2.20.1
In commit b01422622b we did an automated rename of the ptimer_init() function to ptimer_init_with_bh(). Unfortunately this caught the unrelated arm_mptimer_init() function. Undo that accidental renaming. Fixes: b01422622b7c7293196fdaf1dbb4f495af44ecf9 Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Message-id: 20191017133331.5901-1-peter.maydell@linaro.org --- hw/timer/arm_mptimer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c index XXXXXXX..XXXXXXX 100644 --- a/hw/timer/arm_mptimer.c +++ b/hw/timer/arm_mptimer.c @@ -XXX,XX +XXX,XX @@ static void arm_mptimer_reset(DeviceState *dev) } } -static void arm_mptimer_init_with_bh(Object *obj) +static void arm_mptimer_init(Object *obj) { ARMMPTimerState *s = ARM_MPTIMER(obj); @@ -XXX,XX +XXX,XX @@ static const TypeInfo arm_mptimer_info = { .name = TYPE_ARM_MPTIMER, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(ARMMPTimerState), - .instance_init = arm_mptimer_init_with_bh, + .instance_init = arm_mptimer_init, .class_init = arm_mptimer_class_init, }; -- 2.20.1
Switch the puv3_ost code away from bottom-half based ptimers to the new transaction-based ptimer API. This just requires adding begin/commit calls around the various places that modify the ptimer state, and using the new ptimer_init() function to create the timer. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Message-id: 20191017132905.5604-2-peter.maydell@linaro.org --- hw/timer/puv3_ost.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hw/timer/puv3_ost.c b/hw/timer/puv3_ost.c index XXXXXXX..XXXXXXX 100644 --- a/hw/timer/puv3_ost.c +++ b/hw/timer/puv3_ost.c @@ -XXX,XX +XXX,XX @@ #include "hw/sysbus.h" #include "hw/irq.h" #include "hw/ptimer.h" -#include "qemu/main-loop.h" #include "qemu/module.h" #undef DEBUG_PUV3 @@ -XXX,XX +XXX,XX @@ typedef struct PUV3OSTState { SysBusDevice parent_obj; MemoryRegion iomem; - QEMUBH *bh; qemu_irq irq; ptimer_state *ptimer; @@ -XXX,XX +XXX,XX @@ static void puv3_ost_write(void *opaque, hwaddr offset, DPRINTF("offset 0x%x, value 0x%x\n", offset, value); switch (offset) { case 0x00: /* Match Register 0 */ + ptimer_transaction_begin(s->ptimer); s->reg_OSMR0 = value; if (s->reg_OSMR0 > s->reg_OSCR) { ptimer_set_count(s->ptimer, s->reg_OSMR0 - s->reg_OSCR); @@ -XXX,XX +XXX,XX @@ static void puv3_ost_write(void *opaque, hwaddr offset, (0xffffffff - s->reg_OSCR)); } ptimer_run(s->ptimer, 2); + ptimer_transaction_commit(s->ptimer); break; case 0x14: /* Status Register */ assert(value == 0); @@ -XXX,XX +XXX,XX @@ static void puv3_ost_realize(DeviceState *dev, Error **errp) sysbus_init_irq(sbd, &s->irq); - s->bh = qemu_bh_new(puv3_ost_tick, s); - s->ptimer = ptimer_init_with_bh(s->bh, PTIMER_POLICY_DEFAULT); + s->ptimer = ptimer_init(puv3_ost_tick, s, PTIMER_POLICY_DEFAULT); + ptimer_transaction_begin(s->ptimer); ptimer_set_freq(s->ptimer, 50 * 1000 * 1000); + ptimer_transaction_commit(s->ptimer); memory_region_init_io(&s->iomem, OBJECT(s), &puv3_ost_ops, s, "puv3_ost", PUV3_REGS_OFFSET); -- 2.20.1
Switch the sh_timer code away from bottom-half based ptimers to the new transaction-based ptimer API. This just requires adding begin/commit calls around the various places that modify the ptimer state, and using the new ptimer_init() function to create the timer. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Message-id: 20191017132905.5604-3-peter.maydell@linaro.org --- hw/timer/sh_timer.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/hw/timer/sh_timer.c b/hw/timer/sh_timer.c index XXXXXXX..XXXXXXX 100644 --- a/hw/timer/sh_timer.c +++ b/hw/timer/sh_timer.c @@ -XXX,XX +XXX,XX @@ #include "hw/irq.h" #include "hw/sh4/sh.h" #include "qemu/timer.h" -#include "qemu/main-loop.h" #include "hw/ptimer.h" //#define DEBUG_TIMER @@ -XXX,XX +XXX,XX @@ static void sh_timer_write(void *opaque, hwaddr offset, switch (offset >> 2) { case OFFSET_TCOR: s->tcor = value; + ptimer_transaction_begin(s->timer); ptimer_set_limit(s->timer, s->tcor, 0); + ptimer_transaction_commit(s->timer); break; case OFFSET_TCNT: s->tcnt = value; + ptimer_transaction_begin(s->timer); ptimer_set_count(s->timer, s->tcnt); + ptimer_transaction_commit(s->timer); break; case OFFSET_TCR: + ptimer_transaction_begin(s->timer); if (s->enabled) { /* Pause the timer if it is running. This may cause some inaccuracy dure to rounding, but avoids a whole lot of other @@ -XXX,XX +XXX,XX @@ static void sh_timer_write(void *opaque, hwaddr offset, /* Restart the timer if still enabled. */ ptimer_run(s->timer, 0); } + ptimer_transaction_commit(s->timer); break; case OFFSET_TCPR: if (s->feat & TIMER_FEAT_CAPT) { @@ -XXX,XX +XXX,XX @@ static void sh_timer_start_stop(void *opaque, int enable) printf("sh_timer_start_stop %d (%d)\n", enable, s->enabled); #endif + ptimer_transaction_begin(s->timer); if (s->enabled && !enable) { ptimer_stop(s->timer); } if (!s->enabled && enable) { ptimer_run(s->timer, 0); } + ptimer_transaction_commit(s->timer); s->enabled = !!enable; #ifdef DEBUG_TIMER @@ -XXX,XX +XXX,XX @@ static void sh_timer_tick(void *opaque) static void *sh_timer_init(uint32_t freq, int feat, qemu_irq irq) { sh_timer_state *s; - QEMUBH *bh; s = (sh_timer_state *)g_malloc0(sizeof(sh_timer_state)); s->freq = freq; @@ -XXX,XX +XXX,XX @@ static void *sh_timer_init(uint32_t freq, int feat, qemu_irq irq) s->enabled = 0; s->irq = irq; - bh = qemu_bh_new(sh_timer_tick, s); - s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT); + s->timer = ptimer_init(sh_timer_tick, s, PTIMER_POLICY_DEFAULT); sh_timer_write(s, OFFSET_TCOR >> 2, s->tcor); sh_timer_write(s, OFFSET_TCNT >> 2, s->tcnt); -- 2.20.1
Switch the lm32_timer code away from bottom-half based ptimers to the new transaction-based ptimer API. This just requires adding begin/commit calls around the various places that modify the ptimer state, and using the new ptimer_init() function to create the ytimer. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Message-id: 20191017132905.5604-4-peter.maydell@linaro.org --- hw/timer/lm32_timer.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/hw/timer/lm32_timer.c b/hw/timer/lm32_timer.c index XXXXXXX..XXXXXXX 100644 --- a/hw/timer/lm32_timer.c +++ b/hw/timer/lm32_timer.c @@ -XXX,XX +XXX,XX @@ #include "hw/ptimer.h" #include "hw/qdev-properties.h" #include "qemu/error-report.h" -#include "qemu/main-loop.h" #include "qemu/module.h" #define DEFAULT_FREQUENCY (50*1000000) @@ -XXX,XX +XXX,XX @@ struct LM32TimerState { MemoryRegion iomem; - QEMUBH *bh; ptimer_state *ptimer; qemu_irq irq; @@ -XXX,XX +XXX,XX @@ static void timer_write(void *opaque, hwaddr addr, s->regs[R_SR] &= ~SR_TO; break; case R_CR: + ptimer_transaction_begin(s->ptimer); s->regs[R_CR] = value; if (s->regs[R_CR] & CR_START) { ptimer_run(s->ptimer, 1); @@ -XXX,XX +XXX,XX @@ static void timer_write(void *opaque, hwaddr addr, if (s->regs[R_CR] & CR_STOP) { ptimer_stop(s->ptimer); } + ptimer_transaction_commit(s->ptimer); break; case R_PERIOD: s->regs[R_PERIOD] = value; + ptimer_transaction_begin(s->ptimer); ptimer_set_count(s->ptimer, value); + ptimer_transaction_commit(s->ptimer); break; case R_SNAPSHOT: error_report("lm32_timer: write access to read only register 0x" @@ -XXX,XX +XXX,XX @@ static void timer_reset(DeviceState *d) for (i = 0; i < R_MAX; i++) { s->regs[i] = 0; } + ptimer_transaction_begin(s->ptimer); ptimer_stop(s->ptimer); + ptimer_transaction_commit(s->ptimer); } static void lm32_timer_init(Object *obj) @@ -XXX,XX +XXX,XX @@ static void lm32_timer_realize(DeviceState *dev, Error **errp) { LM32TimerState *s = LM32_TIMER(dev); - s->bh = qemu_bh_new(timer_hit, s); - s->ptimer = ptimer_init_with_bh(s->bh, PTIMER_POLICY_DEFAULT); + s->ptimer = ptimer_init(timer_hit, s, PTIMER_POLICY_DEFAULT); + ptimer_transaction_begin(s->ptimer); ptimer_set_freq(s->ptimer, s->freq_hz); + ptimer_transaction_commit(s->ptimer); } static const VMStateDescription vmstate_lm32_timer = { -- 2.20.1
Switch the altera_timer code away from bottom-half based ptimers to the new transaction-based ptimer API. This just requires adding begin/commit calls around the various places that modify the ptimer state, and using the new ptimer_init() function to create the timer. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Message-id: 20191017132905.5604-6-peter.maydell@linaro.org --- hw/timer/altera_timer.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/hw/timer/altera_timer.c b/hw/timer/altera_timer.c index XXXXXXX..XXXXXXX 100644 --- a/hw/timer/altera_timer.c +++ b/hw/timer/altera_timer.c @@ -XXX,XX +XXX,XX @@ */ #include "qemu/osdep.h" -#include "qemu/main-loop.h" #include "qemu/module.h" #include "qapi/error.h" @@ -XXX,XX +XXX,XX @@ typedef struct AlteraTimer { MemoryRegion mmio; qemu_irq irq; uint32_t freq_hz; - QEMUBH *bh; ptimer_state *ptimer; uint32_t regs[R_MAX]; } AlteraTimer; @@ -XXX,XX +XXX,XX @@ static void timer_write(void *opaque, hwaddr addr, break; case R_CONTROL: + ptimer_transaction_begin(t->ptimer); t->regs[R_CONTROL] = value & (CONTROL_ITO | CONTROL_CONT); if ((value & CONTROL_START) && !(t->regs[R_STATUS] & STATUS_RUN)) { @@ -XXX,XX +XXX,XX @@ static void timer_write(void *opaque, hwaddr addr, ptimer_stop(t->ptimer); t->regs[R_STATUS] &= ~STATUS_RUN; } + ptimer_transaction_commit(t->ptimer); break; case R_PERIODL: case R_PERIODH: + ptimer_transaction_begin(t->ptimer); t->regs[addr] = value & 0xFFFF; if (t->regs[R_STATUS] & STATUS_RUN) { ptimer_stop(t->ptimer); @@ -XXX,XX +XXX,XX @@ static void timer_write(void *opaque, hwaddr addr, } tvalue = (t->regs[R_PERIODH] << 16) | t->regs[R_PERIODL]; ptimer_set_limit(t->ptimer, tvalue + 1, 1); + ptimer_transaction_commit(t->ptimer); break; case R_SNAPL: @@ -XXX,XX +XXX,XX @@ static void altera_timer_realize(DeviceState *dev, Error **errp) return; } - t->bh = qemu_bh_new(timer_hit, t); - t->ptimer = ptimer_init_with_bh(t->bh, PTIMER_POLICY_DEFAULT); + t->ptimer = ptimer_init(timer_hit, t, PTIMER_POLICY_DEFAULT); + ptimer_transaction_begin(t->ptimer); ptimer_set_freq(t->ptimer, t->freq_hz); + ptimer_transaction_commit(t->ptimer); memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t, TYPE_ALTERA_TIMER, R_MAX * sizeof(uint32_t)); @@ -XXX,XX +XXX,XX @@ static void altera_timer_reset(DeviceState *dev) { AlteraTimer *t = ALTERA_TIMER(dev); + ptimer_transaction_begin(t->ptimer); ptimer_stop(t->ptimer); ptimer_set_limit(t->ptimer, 0xffffffff, 1); + ptimer_transaction_commit(t->ptimer); memset(t->regs, 0, sizeof(t->regs)); } -- 2.20.1
Switch the etraxfs_timer code away from bottom-half based ptimers to the new transaction-based ptimer API. This just requires adding begin/commit calls around the various places that modify the ptimer state, and using the new ptimer_init() function to create the timer. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Message-id: 20191017132905.5604-7-peter.maydell@linaro.org --- hw/timer/etraxfs_timer.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/hw/timer/etraxfs_timer.c b/hw/timer/etraxfs_timer.c index XXXXXXX..XXXXXXX 100644 --- a/hw/timer/etraxfs_timer.c +++ b/hw/timer/etraxfs_timer.c @@ -XXX,XX +XXX,XX @@ #include "hw/sysbus.h" #include "sysemu/reset.h" #include "sysemu/runstate.h" -#include "qemu/main-loop.h" #include "qemu/module.h" #include "qemu/timer.h" #include "hw/irq.h" @@ -XXX,XX +XXX,XX @@ typedef struct ETRAXTimerState { qemu_irq irq; qemu_irq nmi; - QEMUBH *bh_t0; - QEMUBH *bh_t1; - QEMUBH *bh_wd; ptimer_state *ptimer_t0; ptimer_state *ptimer_t1; ptimer_state *ptimer_wd; @@ -XXX,XX +XXX,XX @@ static void update_ctrl(ETRAXTimerState *t, int tnum) } D(printf ("freq_hz=%d div=%d\n", freq_hz, div)); + ptimer_transaction_begin(timer); ptimer_set_freq(timer, freq_hz); ptimer_set_limit(timer, div, 0); @@ -XXX,XX +XXX,XX @@ static void update_ctrl(ETRAXTimerState *t, int tnum) abort(); break; } + ptimer_transaction_commit(timer); } static void timer_update_irq(ETRAXTimerState *t) @@ -XXX,XX +XXX,XX @@ static inline void timer_watchdog_update(ETRAXTimerState *t, uint32_t value) t->wd_hits = 0; + ptimer_transaction_begin(t->ptimer_wd); ptimer_set_freq(t->ptimer_wd, 760); if (wd_cnt == 0) wd_cnt = 256; @@ -XXX,XX +XXX,XX @@ static inline void timer_watchdog_update(ETRAXTimerState *t, uint32_t value) ptimer_stop(t->ptimer_wd); t->rw_wd_ctrl = value; + ptimer_transaction_commit(t->ptimer_wd); } static void @@ -XXX,XX +XXX,XX @@ static void etraxfs_timer_reset(void *opaque) { ETRAXTimerState *t = opaque; + ptimer_transaction_begin(t->ptimer_t0); ptimer_stop(t->ptimer_t0); + ptimer_transaction_commit(t->ptimer_t0); + ptimer_transaction_begin(t->ptimer_t1); ptimer_stop(t->ptimer_t1); + ptimer_transaction_commit(t->ptimer_t1); + ptimer_transaction_begin(t->ptimer_wd); ptimer_stop(t->ptimer_wd); + ptimer_transaction_commit(t->ptimer_wd); t->rw_wd_ctrl = 0; t->r_intr = 0; t->rw_intr_mask = 0; @@ -XXX,XX +XXX,XX @@ static void etraxfs_timer_realize(DeviceState *dev, Error **errp) ETRAXTimerState *t = ETRAX_TIMER(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - t->bh_t0 = qemu_bh_new(timer0_hit, t); - t->bh_t1 = qemu_bh_new(timer1_hit, t); - t->bh_wd = qemu_bh_new(watchdog_hit, t); - t->ptimer_t0 = ptimer_init_with_bh(t->bh_t0, PTIMER_POLICY_DEFAULT); - t->ptimer_t1 = ptimer_init_with_bh(t->bh_t1, PTIMER_POLICY_DEFAULT); - t->ptimer_wd = ptimer_init_with_bh(t->bh_wd, PTIMER_POLICY_DEFAULT); + t->ptimer_t0 = ptimer_init(timer0_hit, t, PTIMER_POLICY_DEFAULT); + t->ptimer_t1 = ptimer_init(timer1_hit, t, PTIMER_POLICY_DEFAULT); + t->ptimer_wd = ptimer_init(watchdog_hit, t, PTIMER_POLICY_DEFAULT); sysbus_init_irq(sbd, &t->irq); sysbus_init_irq(sbd, &t->nmi); -- 2.20.1
Switch the mcf5208 code away from bottom-half based ptimers to the new transaction-based ptimer API. This just requires adding begin/commit calls around the various places that modify the ptimer state, and using the new ptimer_init() function to create the timer. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Tested-by: Thomas Huth <huth@tuxfamily.org> Message-id: 20191017132905.5604-9-peter.maydell@linaro.org --- hw/m68k/mcf5208.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c index XXXXXXX..XXXXXXX 100644 --- a/hw/m68k/mcf5208.c +++ b/hw/m68k/mcf5208.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qemu/error-report.h" -#include "qemu/main-loop.h" #include "qapi/error.h" #include "qemu-common.h" #include "cpu.h" @@ -XXX,XX +XXX,XX @@ static void m5208_timer_write(void *opaque, hwaddr offset, return; } + ptimer_transaction_begin(s->timer); if (s->pcsr & PCSR_EN) ptimer_stop(s->timer); @@ -XXX,XX +XXX,XX @@ static void m5208_timer_write(void *opaque, hwaddr offset, if (s->pcsr & PCSR_EN) ptimer_run(s->timer, 0); + ptimer_transaction_commit(s->timer); break; case 2: + ptimer_transaction_begin(s->timer); s->pmr = value; s->pcsr &= ~PCSR_PIF; if ((s->pcsr & PCSR_RLD) == 0) { @@ -XXX,XX +XXX,XX @@ static void m5208_timer_write(void *opaque, hwaddr offset, } else { ptimer_set_limit(s->timer, value, s->pcsr & PCSR_OVW); } + ptimer_transaction_commit(s->timer); break; case 4: break; @@ -XXX,XX +XXX,XX @@ static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic) { MemoryRegion *iomem = g_new(MemoryRegion, 1); m5208_timer_state *s; - QEMUBH *bh; int i; /* SDRAMC. */ @@ -XXX,XX +XXX,XX @@ static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic) /* Timers. */ for (i = 0; i < 2; i++) { s = g_new0(m5208_timer_state, 1); - bh = qemu_bh_new(m5208_timer_trigger, s); - s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT); + s->timer = ptimer_init(m5208_timer_trigger, s, PTIMER_POLICY_DEFAULT); memory_region_init_io(&s->iomem, NULL, &m5208_timer_ops, s, "m5208-timer", 0x00004000); memory_region_add_subregion(address_space, 0xfc080000 + 0x4000 * i, -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> Create a function to compute the values of the TBFLAG_ANY bits that will be cached. For now, the env->hflags variable is not used, and the results are fed back to cpu_get_tb_cpu_state. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-2-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpu.h | 29 ++++++++++++++++++----------- target/arm/helper.c | 26 +++++++++++++++++++------- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState { uint32_t pstate; uint32_t aarch64; /* 1 if CPU is in aarch64 state; inverse of PSTATE.nRW */ + /* Cached TBFLAGS state. See below for which bits are included. */ + uint32_t hflags; + /* Frequently accessed CPSR bits are stored separately for efficiency. This contains all the other bits. Use cpsr_{read,write} to access the whole CPSR. */ @@ -XXX,XX +XXX,XX @@ typedef ARMCPU ArchCPU; #include "exec/cpu-all.h" -/* Bit usage in the TB flags field: bit 31 indicates whether we are +/* + * Bit usage in the TB flags field: bit 31 indicates whether we are * in 32 or 64 bit mode. The meaning of the other bits depends on that. * We put flags which are shared between 32 and 64 bit mode at the top * of the word, and flags which apply to only one mode at the bottom. + * + * Unless otherwise noted, these bits are cached in env->hflags. */ FIELD(TBFLAG_ANY, AARCH64_STATE, 31, 1) FIELD(TBFLAG_ANY, MMUIDX, 28, 3) FIELD(TBFLAG_ANY, SS_ACTIVE, 27, 1) -FIELD(TBFLAG_ANY, PSTATE_SS, 26, 1) +FIELD(TBFLAG_ANY, PSTATE_SS, 26, 1) /* Not cached. */ /* Target EL if we take a floating-point-disabled exception */ FIELD(TBFLAG_ANY, FPEXC_EL, 24, 2) FIELD(TBFLAG_ANY, BE_DATA, 23, 1) @@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_ANY, BE_DATA, 23, 1) FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 21, 2) /* Bit usage when in AArch32 state: */ -FIELD(TBFLAG_A32, THUMB, 0, 1) -FIELD(TBFLAG_A32, VECLEN, 1, 3) -FIELD(TBFLAG_A32, VECSTRIDE, 4, 2) +FIELD(TBFLAG_A32, THUMB, 0, 1) /* Not cached. */ +FIELD(TBFLAG_A32, VECLEN, 1, 3) /* Not cached. */ +FIELD(TBFLAG_A32, VECSTRIDE, 4, 2) /* Not cached. */ /* * We store the bottom two bits of the CPAR as TB flags and handle * checks on the other bits at runtime. This shares the same bits as * VECSTRIDE, which is OK as no XScale CPU has VFP. + * Not cached, because VECLEN+VECSTRIDE are not cached. */ FIELD(TBFLAG_A32, XSCALE_CPAR, 4, 2) /* @@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, XSCALE_CPAR, 4, 2) * the same thing as the current security state of the processor! */ FIELD(TBFLAG_A32, NS, 6, 1) -FIELD(TBFLAG_A32, VFPEN, 7, 1) -FIELD(TBFLAG_A32, CONDEXEC, 8, 8) +FIELD(TBFLAG_A32, VFPEN, 7, 1) /* Not cached. */ +FIELD(TBFLAG_A32, CONDEXEC, 8, 8) /* Not cached. */ FIELD(TBFLAG_A32, SCTLR_B, 16, 1) /* For M profile only, set if FPCCR.LSPACT is set */ -FIELD(TBFLAG_A32, LSPACT, 18, 1) +FIELD(TBFLAG_A32, LSPACT, 18, 1) /* Not cached. */ /* For M profile only, set if we must create a new FP context */ -FIELD(TBFLAG_A32, NEW_FP_CTXT_NEEDED, 19, 1) +FIELD(TBFLAG_A32, NEW_FP_CTXT_NEEDED, 19, 1) /* Not cached. */ /* For M profile only, set if FPCCR.S does not match current security state */ -FIELD(TBFLAG_A32, FPCCR_S_WRONG, 20, 1) +FIELD(TBFLAG_A32, FPCCR_S_WRONG, 20, 1) /* Not cached. */ /* For M profile only, Handler (ie not Thread) mode */ FIELD(TBFLAG_A32, HANDLER, 21, 1) /* For M profile only, whether we should generate stack-limit checks */ @@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A64, SVEEXC_EL, 2, 2) FIELD(TBFLAG_A64, ZCR_LEN, 4, 4) FIELD(TBFLAG_A64, PAUTH_ACTIVE, 8, 1) FIELD(TBFLAG_A64, BT, 9, 1) -FIELD(TBFLAG_A64, BTYPE, 10, 2) +FIELD(TBFLAG_A64, BTYPE, 10, 2) /* Not cached. */ FIELD(TBFLAG_A64, TBID, 12, 2) static inline bool bswap_code(bool sctlr_b) diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env) } #endif +static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el, + ARMMMUIdx mmu_idx, uint32_t flags) +{ + flags = FIELD_DP32(flags, TBFLAG_ANY, FPEXC_EL, fp_el); + flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX, + arm_to_core_mmu_idx(mmu_idx)); + + if (arm_cpu_data_is_big_endian(env)) { + flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1); + } + if (arm_singlestep_active(env)) { + flags = FIELD_DP32(flags, TBFLAG_ANY, SS_ACTIVE, 1); + } + return flags; +} + void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *pflags) { @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, } } - flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX, arm_to_core_mmu_idx(mmu_idx)); + flags = rebuild_hflags_common(env, fp_el, mmu_idx, flags); /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine * states defined in the ARM ARM for software singlestep: @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, * 0 x Inactive (the TB flag for SS is always 0) * 1 0 Active-pending * 1 1 Active-not-pending + * SS_ACTIVE is set in hflags; PSTATE_SS is computed every TB. */ - if (arm_singlestep_active(env)) { - flags = FIELD_DP32(flags, TBFLAG_ANY, SS_ACTIVE, 1); + if (FIELD_EX32(flags, TBFLAG_ANY, SS_ACTIVE)) { if (is_a64(env)) { if (env->pstate & PSTATE_SS) { flags = FIELD_DP32(flags, TBFLAG_ANY, PSTATE_SS, 1); @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, } } } - if (arm_cpu_data_is_big_endian(env)) { - flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1); - } - flags = FIELD_DP32(flags, TBFLAG_ANY, FPEXC_EL, fp_el); if (arm_v7m_is_handler_mode(env)) { flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1); -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> Create a function to compute the values of the TBFLAG_A64 bits that will be cached. For now, the env->hflags variable is not used, and the results are fed back to cpu_get_tb_cpu_state. Note that not all BTI related flags are cached, so we have to test the BTI feature twice -- once for those bits moved out to rebuild_hflags_a64 and once for those bits that remain in cpu_get_tb_cpu_state. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-3-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper.c | 131 +++++++++++++++++++++++--------------------- 1 file changed, 69 insertions(+), 62 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el, return flags; } +static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, + ARMMMUIdx mmu_idx) +{ + ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx); + ARMVAParameters p0 = aa64_va_parameters_both(env, 0, stage1); + uint32_t flags = 0; + uint64_t sctlr; + int tbii, tbid; + + flags = FIELD_DP32(flags, TBFLAG_ANY, AARCH64_STATE, 1); + + /* FIXME: ARMv8.1-VHE S2 translation regime. */ + if (regime_el(env, stage1) < 2) { + ARMVAParameters p1 = aa64_va_parameters_both(env, -1, stage1); + tbid = (p1.tbi << 1) | p0.tbi; + tbii = tbid & ~((p1.tbid << 1) | p0.tbid); + } else { + tbid = p0.tbi; + tbii = tbid & !p0.tbid; + } + + flags = FIELD_DP32(flags, TBFLAG_A64, TBII, tbii); + flags = FIELD_DP32(flags, TBFLAG_A64, TBID, tbid); + + if (cpu_isar_feature(aa64_sve, env_archcpu(env))) { + int sve_el = sve_exception_el(env, el); + uint32_t zcr_len; + + /* + * If SVE is disabled, but FP is enabled, + * then the effective len is 0. + */ + if (sve_el != 0 && fp_el == 0) { + zcr_len = 0; + } else { + zcr_len = sve_zcr_len_for_el(env, el); + } + flags = FIELD_DP32(flags, TBFLAG_A64, SVEEXC_EL, sve_el); + flags = FIELD_DP32(flags, TBFLAG_A64, ZCR_LEN, zcr_len); + } + + sctlr = arm_sctlr(env, el); + + if (cpu_isar_feature(aa64_pauth, env_archcpu(env))) { + /* + * In order to save space in flags, we record only whether + * pauth is "inactive", meaning all insns are implemented as + * a nop, or "active" when some action must be performed. + * The decision of which action to take is left to a helper. + */ + if (sctlr & (SCTLR_EnIA | SCTLR_EnIB | SCTLR_EnDA | SCTLR_EnDB)) { + flags = FIELD_DP32(flags, TBFLAG_A64, PAUTH_ACTIVE, 1); + } + } + + if (cpu_isar_feature(aa64_bti, env_archcpu(env))) { + /* Note that SCTLR_EL[23].BT == SCTLR_BT1. */ + if (sctlr & (el == 0 ? SCTLR_BT0 : SCTLR_BT1)) { + flags = FIELD_DP32(flags, TBFLAG_A64, BT, 1); + } + } + + return rebuild_hflags_common(env, fp_el, mmu_idx, flags); +} + void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *pflags) { @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, uint32_t flags = 0; if (is_a64(env)) { - ARMCPU *cpu = env_archcpu(env); - uint64_t sctlr; - *pc = env->pc; - flags = FIELD_DP32(flags, TBFLAG_ANY, AARCH64_STATE, 1); - - /* Get control bits for tagged addresses. */ - { - ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx); - ARMVAParameters p0 = aa64_va_parameters_both(env, 0, stage1); - int tbii, tbid; - - /* FIXME: ARMv8.1-VHE S2 translation regime. */ - if (regime_el(env, stage1) < 2) { - ARMVAParameters p1 = aa64_va_parameters_both(env, -1, stage1); - tbid = (p1.tbi << 1) | p0.tbi; - tbii = tbid & ~((p1.tbid << 1) | p0.tbid); - } else { - tbid = p0.tbi; - tbii = tbid & !p0.tbid; - } - - flags = FIELD_DP32(flags, TBFLAG_A64, TBII, tbii); - flags = FIELD_DP32(flags, TBFLAG_A64, TBID, tbid); - } - - if (cpu_isar_feature(aa64_sve, cpu)) { - int sve_el = sve_exception_el(env, current_el); - uint32_t zcr_len; - - /* If SVE is disabled, but FP is enabled, - * then the effective len is 0. - */ - if (sve_el != 0 && fp_el == 0) { - zcr_len = 0; - } else { - zcr_len = sve_zcr_len_for_el(env, current_el); - } - flags = FIELD_DP32(flags, TBFLAG_A64, SVEEXC_EL, sve_el); - flags = FIELD_DP32(flags, TBFLAG_A64, ZCR_LEN, zcr_len); - } - - sctlr = arm_sctlr(env, current_el); - - if (cpu_isar_feature(aa64_pauth, cpu)) { - /* - * In order to save space in flags, we record only whether - * pauth is "inactive", meaning all insns are implemented as - * a nop, or "active" when some action must be performed. - * The decision of which action to take is left to a helper. - */ - if (sctlr & (SCTLR_EnIA | SCTLR_EnIB | SCTLR_EnDA | SCTLR_EnDB)) { - flags = FIELD_DP32(flags, TBFLAG_A64, PAUTH_ACTIVE, 1); - } - } - - if (cpu_isar_feature(aa64_bti, cpu)) { - /* Note that SCTLR_EL[23].BT == SCTLR_BT1. */ - if (sctlr & (current_el == 0 ? SCTLR_BT0 : SCTLR_BT1)) { - flags = FIELD_DP32(flags, TBFLAG_A64, BT, 1); - } + flags = rebuild_hflags_a64(env, current_el, fp_el, mmu_idx); + if (cpu_isar_feature(aa64_bti, env_archcpu(env))) { flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype); } } else { @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, flags = FIELD_DP32(flags, TBFLAG_A32, XSCALE_CPAR, env->cp15.c15_cpar); } - } - flags = rebuild_hflags_common(env, fp_el, mmu_idx, flags); + flags = rebuild_hflags_common(env, fp_el, mmu_idx, flags); + } /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine * states defined in the ARM ARM for software singlestep: -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> Create a function to compute the values of the TBFLAG_A32 bits that will be cached, and are used by all profiles. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-4-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el, return flags; } +static uint32_t rebuild_hflags_common_32(CPUARMState *env, int fp_el, + ARMMMUIdx mmu_idx, uint32_t flags) +{ + flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, arm_sctlr_b(env)); + flags = FIELD_DP32(flags, TBFLAG_A32, NS, !access_secure_reg(env)); + + return rebuild_hflags_common(env, fp_el, mmu_idx, flags); +} + static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, ARMMMUIdx mmu_idx) { @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, ARMMMUIdx mmu_idx = arm_mmu_idx(env); int current_el = arm_current_el(env); int fp_el = fp_exception_el(env, current_el); - uint32_t flags = 0; + uint32_t flags; if (is_a64(env)) { *pc = env->pc; @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, } } else { *pc = env->regs[15]; + flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0); flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb); flags = FIELD_DP32(flags, TBFLAG_A32, VECLEN, env->vfp.vec_len); flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE, env->vfp.vec_stride); flags = FIELD_DP32(flags, TBFLAG_A32, CONDEXEC, env->condexec_bits); - flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, arm_sctlr_b(env)); - flags = FIELD_DP32(flags, TBFLAG_A32, NS, !access_secure_reg(env)); if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30) || arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) { flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1); @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, flags = FIELD_DP32(flags, TBFLAG_A32, XSCALE_CPAR, env->cp15.c15_cpar); } - - flags = rebuild_hflags_common(env, fp_el, mmu_idx, flags); } /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> Set TBFLAG_ANY.BE_DATA in rebuild_hflags_common_32 and rebuild_hflags_a64 instead of rebuild_hflags_common, where we do not need to re-test is_a64() nor re-compute the various inputs. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-5-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpu.h | 49 +++++++++++++++++++++++++++------------------ target/arm/helper.c | 16 +++++++++++---- 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -XXX,XX +XXX,XX @@ static inline uint64_t arm_sctlr(CPUARMState *env, int el) } } +static inline bool arm_cpu_data_is_big_endian_a32(CPUARMState *env, + bool sctlr_b) +{ +#ifdef CONFIG_USER_ONLY + /* + * In system mode, BE32 is modelled in line with the + * architecture (as word-invariant big-endianness), where loads + * and stores are done little endian but from addresses which + * are adjusted by XORing with the appropriate constant. So the + * endianness to use for the raw data access is not affected by + * SCTLR.B. + * In user mode, however, we model BE32 as byte-invariant + * big-endianness (because user-only code cannot tell the + * difference), and so we need to use a data access endianness + * that depends on SCTLR.B. + */ + if (sctlr_b) { + return true; + } +#endif + /* In 32bit endianness is determined by looking at CPSR's E bit */ + return env->uncached_cpsr & CPSR_E; +} + +static inline bool arm_cpu_data_is_big_endian_a64(int el, uint64_t sctlr) +{ + return sctlr & (el ? SCTLR_EE : SCTLR_E0E); +} /* Return true if the processor is in big-endian mode. */ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env) { - /* In 32bit endianness is determined by looking at CPSR's E bit */ if (!is_a64(env)) { - return -#ifdef CONFIG_USER_ONLY - /* In system mode, BE32 is modelled in line with the - * architecture (as word-invariant big-endianness), where loads - * and stores are done little endian but from addresses which - * are adjusted by XORing with the appropriate constant. So the - * endianness to use for the raw data access is not affected by - * SCTLR.B. - * In user mode, however, we model BE32 as byte-invariant - * big-endianness (because user-only code cannot tell the - * difference), and so we need to use a data access endianness - * that depends on SCTLR.B. - */ - arm_sctlr_b(env) || -#endif - ((env->uncached_cpsr & CPSR_E) ? 1 : 0); + return arm_cpu_data_is_big_endian_a32(env, arm_sctlr_b(env)); } else { int cur_el = arm_current_el(env); uint64_t sctlr = arm_sctlr(env, cur_el); - - return (sctlr & (cur_el ? SCTLR_EE : SCTLR_E0E)) != 0; + return arm_cpu_data_is_big_endian_a64(cur_el, sctlr); } } diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el, flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX, arm_to_core_mmu_idx(mmu_idx)); - if (arm_cpu_data_is_big_endian(env)) { - flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1); - } if (arm_singlestep_active(env)) { flags = FIELD_DP32(flags, TBFLAG_ANY, SS_ACTIVE, 1); } @@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el, static uint32_t rebuild_hflags_common_32(CPUARMState *env, int fp_el, ARMMMUIdx mmu_idx, uint32_t flags) { - flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, arm_sctlr_b(env)); + bool sctlr_b = arm_sctlr_b(env); + + if (sctlr_b) { + flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, 1); + } + if (arm_cpu_data_is_big_endian_a32(env, sctlr_b)) { + flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1); + } flags = FIELD_DP32(flags, TBFLAG_A32, NS, !access_secure_reg(env)); return rebuild_hflags_common(env, fp_el, mmu_idx, flags); @@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, sctlr = arm_sctlr(env, el); + if (arm_cpu_data_is_big_endian_a64(el, sctlr)) { + flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1); + } + if (cpu_isar_feature(aa64_pauth, env_archcpu(env))) { /* * In order to save space in flags, we record only whether -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> Create a function to compute the values of the TBFLAG_A32 bits that will be cached, and are used by M-profile. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-6-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper.c | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common_32(CPUARMState *env, int fp_el, return rebuild_hflags_common(env, fp_el, mmu_idx, flags); } +static uint32_t rebuild_hflags_m32(CPUARMState *env, int fp_el, + ARMMMUIdx mmu_idx) +{ + uint32_t flags = 0; + + if (arm_v7m_is_handler_mode(env)) { + flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1); + } + + /* + * v8M always applies stack limit checks unless CCR.STKOFHFNMIGN + * is suppressing them because the requested execution priority + * is less than 0. + */ + if (arm_feature(env, ARM_FEATURE_V8) && + !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) && + (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKOFHFNMIGN_MASK))) { + flags = FIELD_DP32(flags, TBFLAG_A32, STACKCHECK, 1); + } + + return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); +} + static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, ARMMMUIdx mmu_idx) { @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, } } else { *pc = env->regs[15]; - flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0); + + if (arm_feature(env, ARM_FEATURE_M)) { + flags = rebuild_hflags_m32(env, fp_el, mmu_idx); + } else { + flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0); + } + flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb); flags = FIELD_DP32(flags, TBFLAG_A32, VECLEN, env->vfp.vec_len); flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE, env->vfp.vec_stride); @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, } } - if (arm_v7m_is_handler_mode(env)) { - flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1); - } - - /* v8M always applies stack limit checks unless CCR.STKOFHFNMIGN is - * suppressing them because the requested execution priority is less than 0. - */ - if (arm_feature(env, ARM_FEATURE_V8) && - arm_feature(env, ARM_FEATURE_M) && - !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) && - (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKOFHFNMIGN_MASK))) { - flags = FIELD_DP32(flags, TBFLAG_A32, STACKCHECK, 1); - } - if (arm_feature(env, ARM_FEATURE_M_SECURITY) && FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S) != env->v7m.secure) { flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1); -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> Hoist the computation of some TBFLAG_A32 bits that only apply to M-profile under a single test for ARM_FEATURE_M. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-7-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper.c | 49 +++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, if (arm_feature(env, ARM_FEATURE_M)) { flags = rebuild_hflags_m32(env, fp_el, mmu_idx); + + if (arm_feature(env, ARM_FEATURE_M_SECURITY) && + FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S) + != env->v7m.secure) { + flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1); + } + + if ((env->v7m.fpccr[env->v7m.secure] & R_V7M_FPCCR_ASPEN_MASK) && + (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) || + (env->v7m.secure && + !(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)))) { + /* + * ASPEN is set, but FPCA/SFPA indicate that there is no + * active FP context; we must create a new FP context before + * executing any FP insn. + */ + flags = FIELD_DP32(flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED, 1); + } + + bool is_secure = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK; + if (env->v7m.fpccr[is_secure] & R_V7M_FPCCR_LSPACT_MASK) { + flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1); + } } else { flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0); } @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, } } - if (arm_feature(env, ARM_FEATURE_M_SECURITY) && - FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S) != env->v7m.secure) { - flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1); - } - - if (arm_feature(env, ARM_FEATURE_M) && - (env->v7m.fpccr[env->v7m.secure] & R_V7M_FPCCR_ASPEN_MASK) && - (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) || - (env->v7m.secure && - !(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)))) { - /* - * ASPEN is set, but FPCA/SFPA indicate that there is no active - * FP context; we must create a new FP context before executing - * any FP insn. - */ - flags = FIELD_DP32(flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED, 1); - } - - if (arm_feature(env, ARM_FEATURE_M)) { - bool is_secure = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK; - - if (env->v7m.fpccr[is_secure] & R_V7M_FPCCR_LSPACT_MASK) { - flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1); - } - } - if (!arm_feature(env, ARM_FEATURE_M)) { int target_el = arm_debug_target_el(env); -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> Currently a trivial wrapper for rebuild_hflags_common_32. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-8-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_m32(CPUARMState *env, int fp_el, return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); } +static uint32_t rebuild_hflags_a32(CPUARMState *env, int fp_el, + ARMMMUIdx mmu_idx) +{ + return rebuild_hflags_common_32(env, fp_el, mmu_idx, 0); +} + static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, ARMMMUIdx mmu_idx) { @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1); } } else { - flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0); + flags = rebuild_hflags_a32(env, fp_el, mmu_idx); } flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb); -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> Create a function to compute the values of the TBFLAG_ANY bits that will be cached, and are used by A-profile. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-9-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_m32(CPUARMState *env, int fp_el, return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); } +static uint32_t rebuild_hflags_aprofile(CPUARMState *env) +{ + int flags = 0; + + flags = FIELD_DP32(flags, TBFLAG_ANY, DEBUG_TARGET_EL, + arm_debug_target_el(env)); + return flags; +} + static uint32_t rebuild_hflags_a32(CPUARMState *env, int fp_el, ARMMMUIdx mmu_idx) { - return rebuild_hflags_common_32(env, fp_el, mmu_idx, 0); + uint32_t flags = rebuild_hflags_aprofile(env); + return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); } static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, ARMMMUIdx mmu_idx) { + uint32_t flags = rebuild_hflags_aprofile(env); ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx); ARMVAParameters p0 = aa64_va_parameters_both(env, 0, stage1); - uint32_t flags = 0; uint64_t sctlr; int tbii, tbid; @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, } } - if (!arm_feature(env, ARM_FEATURE_M)) { - int target_el = arm_debug_target_el(env); - - flags = FIELD_DP32(flags, TBFLAG_ANY, DEBUG_TARGET_EL, target_el); - } - *pflags = flags; *cs_base = 0; } -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> We do not need to compute any of these values for M-profile. Further, XSCALE_CPAR overlaps VECSTRIDE so obviously the two sets must be mutually exclusive. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-10-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, } } else { flags = rebuild_hflags_a32(env, fp_el, mmu_idx); + + /* + * Note that XSCALE_CPAR shares bits with VECSTRIDE. + * Note that VECLEN+VECSTRIDE are RES0 for M-profile. + */ + if (arm_feature(env, ARM_FEATURE_XSCALE)) { + flags = FIELD_DP32(flags, TBFLAG_A32, + XSCALE_CPAR, env->cp15.c15_cpar); + } else { + flags = FIELD_DP32(flags, TBFLAG_A32, VECLEN, + env->vfp.vec_len); + flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE, + env->vfp.vec_stride); + } } flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb); - flags = FIELD_DP32(flags, TBFLAG_A32, VECLEN, env->vfp.vec_len); - flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE, env->vfp.vec_stride); flags = FIELD_DP32(flags, TBFLAG_A32, CONDEXEC, env->condexec_bits); if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30) || arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) { flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1); } - /* Note that XSCALE_CPAR shares bits with VECSTRIDE */ - if (arm_feature(env, ARM_FEATURE_XSCALE)) { - flags = FIELD_DP32(flags, TBFLAG_A32, - XSCALE_CPAR, env->cp15.c15_cpar); - } } /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> Hoist the variable load for PSTATE into the existing test vs is_a64. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-11-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, ARMMMUIdx mmu_idx = arm_mmu_idx(env); int current_el = arm_current_el(env); int fp_el = fp_exception_el(env, current_el); - uint32_t flags; + uint32_t flags, pstate_for_ss; if (is_a64(env)) { *pc = env->pc; @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, if (cpu_isar_feature(aa64_bti, env_archcpu(env))) { flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype); } + pstate_for_ss = env->pstate; } else { *pc = env->regs[15]; @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, || arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) { flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1); } + pstate_for_ss = env->uncached_cpsr; } - /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine + /* + * The SS_ACTIVE and PSTATE_SS bits correspond to the state machine * states defined in the ARM ARM for software singlestep: * SS_ACTIVE PSTATE.SS State * 0 x Inactive (the TB flag for SS is always 0) @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, * 1 1 Active-not-pending * SS_ACTIVE is set in hflags; PSTATE_SS is computed every TB. */ - if (FIELD_EX32(flags, TBFLAG_ANY, SS_ACTIVE)) { - if (is_a64(env)) { - if (env->pstate & PSTATE_SS) { - flags = FIELD_DP32(flags, TBFLAG_ANY, PSTATE_SS, 1); - } - } else { - if (env->uncached_cpsr & PSTATE_SS) { - flags = FIELD_DP32(flags, TBFLAG_ANY, PSTATE_SS, 1); - } - } + if (FIELD_EX32(flags, TBFLAG_ANY, SS_ACTIVE) && + (pstate_for_ss & PSTATE_SS)) { + flags = FIELD_DP32(flags, TBFLAG_ANY, PSTATE_SS, 1); } *pflags = flags; -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> There are 3 conditions that each enable this flag. M-profile always enables; A-profile with EL1 as AA64 always enables. Both of these conditions can easily be cached. The final condition relies on the FPEXC register which we are not prepared to cache. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-12-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpu.h | 2 +- target/arm/helper.c | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, XSCALE_CPAR, 4, 2) * the same thing as the current security state of the processor! */ FIELD(TBFLAG_A32, NS, 6, 1) -FIELD(TBFLAG_A32, VFPEN, 7, 1) /* Not cached. */ +FIELD(TBFLAG_A32, VFPEN, 7, 1) /* Partially cached, minus FPEXC. */ FIELD(TBFLAG_A32, CONDEXEC, 8, 8) /* Not cached. */ FIELD(TBFLAG_A32, SCTLR_B, 16, 1) /* For M profile only, set if FPCCR.LSPACT is set */ diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_m32(CPUARMState *env, int fp_el, { uint32_t flags = 0; + /* v8M always enables the fpu. */ + flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1); + if (arm_v7m_is_handler_mode(env)) { flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1); } @@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a32(CPUARMState *env, int fp_el, ARMMMUIdx mmu_idx) { uint32_t flags = rebuild_hflags_aprofile(env); + + if (arm_el_is_aa64(env, 1)) { + flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1); + } return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); } @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE, env->vfp.vec_stride); } + if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) { + flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1); + } } flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb); flags = FIELD_DP32(flags, TBFLAG_A32, CONDEXEC, env->condexec_bits); - if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30) - || arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) { - flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1); - } pstate_for_ss = env->uncached_cpsr; } -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> This function assumes nothing about the current state of the cpu, and writes the computed value to env->hflags. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-13-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpu.h | 6 ++++++ target/arm/helper.c | 30 ++++++++++++++++++++++-------- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -XXX,XX +XXX,XX @@ void arm_register_pre_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook, void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook, void *opaque); +/** + * arm_rebuild_hflags: + * Rebuild the cached TBFLAGS for arbitrary changed processor state. + */ +void arm_rebuild_hflags(CPUARMState *env); + /** * aa32_vfp_dreg: * Return a pointer to the Dn register within env in 32-bit mode. diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, return rebuild_hflags_common(env, fp_el, mmu_idx, flags); } +static uint32_t rebuild_hflags_internal(CPUARMState *env) +{ + int el = arm_current_el(env); + int fp_el = fp_exception_el(env, el); + ARMMMUIdx mmu_idx = arm_mmu_idx(env); + + if (is_a64(env)) { + return rebuild_hflags_a64(env, el, fp_el, mmu_idx); + } else if (arm_feature(env, ARM_FEATURE_M)) { + return rebuild_hflags_m32(env, fp_el, mmu_idx); + } else { + return rebuild_hflags_a32(env, fp_el, mmu_idx); + } +} + +void arm_rebuild_hflags(CPUARMState *env) +{ + env->hflags = rebuild_hflags_internal(env); +} + void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *pflags) { - ARMMMUIdx mmu_idx = arm_mmu_idx(env); - int current_el = arm_current_el(env); - int fp_el = fp_exception_el(env, current_el); uint32_t flags, pstate_for_ss; + flags = rebuild_hflags_internal(env); + if (is_a64(env)) { *pc = env->pc; - flags = rebuild_hflags_a64(env, current_el, fp_el, mmu_idx); if (cpu_isar_feature(aa64_bti, env_archcpu(env))) { flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype); } @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, *pc = env->regs[15]; if (arm_feature(env, ARM_FEATURE_M)) { - flags = rebuild_hflags_m32(env, fp_el, mmu_idx); - if (arm_feature(env, ARM_FEATURE_M_SECURITY) && FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S) != env->v7m.secure) { @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1); } } else { - flags = rebuild_hflags_a32(env, fp_el, mmu_idx); - /* * Note that XSCALE_CPAR shares bits with VECSTRIDE. * Note that VECLEN+VECSTRIDE are RES0 for M-profile. -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> Avoid calling arm_current_el() twice. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-14-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/internals.h | 9 +++++++++ target/arm/helper.c | 12 +++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/target/arm/internals.h b/target/arm/internals.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -XXX,XX +XXX,XX @@ void arm_cpu_update_virq(ARMCPU *cpu); */ void arm_cpu_update_vfiq(ARMCPU *cpu); +/** + * arm_mmu_idx_el: + * @env: The cpu environment + * @el: The EL to use. + * + * Return the full ARMMMUIdx for the translation regime for EL. + */ +ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el); + /** * arm_mmu_idx: * @env: The cpu environment diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate) } #endif -ARMMMUIdx arm_mmu_idx(CPUARMState *env) +ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el) { - int el; - if (arm_feature(env, ARM_FEATURE_M)) { return arm_v7m_mmu_idx_for_secstate(env, env->v7m.secure); } - el = arm_current_el(env); if (el < 2 && arm_is_secure_below_el3(env)) { return ARMMMUIdx_S1SE0 + el; } else { @@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_mmu_idx(CPUARMState *env) } } +ARMMMUIdx arm_mmu_idx(CPUARMState *env) +{ + return arm_mmu_idx_el(env, arm_current_el(env)); +} + int cpu_mmu_index(CPUARMState *env, bool ifetch) { return arm_to_core_mmu_idx(arm_mmu_idx(env)); @@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_internal(CPUARMState *env) { int el = arm_current_el(env); int fp_el = fp_exception_el(env, el); - ARMMMUIdx mmu_idx = arm_mmu_idx(env); + ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); if (is_a64(env)) { return rebuild_hflags_a64(env, el, fp_el, mmu_idx); -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> By performing this store early, we avoid having to save and restore the register holding the address around any function calls. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-15-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, { uint32_t flags, pstate_for_ss; + *cs_base = 0; flags = rebuild_hflags_internal(env); if (is_a64(env)) { @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, } *pflags = flags; - *cs_base = 0; } #ifdef TARGET_AARCH64 -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> This functions are given the mode and el state of the cpu and writes the computed value to env->hflags. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-16-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper.h | 4 ++++ target/arm/helper.c | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/target/arm/helper.h b/target/arm/helper.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -XXX,XX +XXX,XX @@ DEF_HELPER_4(msr_banked, void, env, i32, i32, i32) DEF_HELPER_2(get_user_reg, i32, env, i32) DEF_HELPER_3(set_user_reg, void, env, i32, i32) +DEF_HELPER_FLAGS_2(rebuild_hflags_m32, TCG_CALL_NO_RWG, void, env, int) +DEF_HELPER_FLAGS_2(rebuild_hflags_a32, TCG_CALL_NO_RWG, void, env, int) +DEF_HELPER_FLAGS_2(rebuild_hflags_a64, TCG_CALL_NO_RWG, void, env, int) + DEF_HELPER_1(vfp_get_fpscr, i32, env) DEF_HELPER_2(vfp_set_fpscr, void, env, i32) diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ void arm_rebuild_hflags(CPUARMState *env) env->hflags = rebuild_hflags_internal(env); } +void HELPER(rebuild_hflags_m32)(CPUARMState *env, int el) +{ + int fp_el = fp_exception_el(env, el); + ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); + + env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx); +} + +void HELPER(rebuild_hflags_a32)(CPUARMState *env, int el) +{ + int fp_el = fp_exception_el(env, el); + ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); + + env->hflags = rebuild_hflags_a32(env, fp_el, mmu_idx); +} + +void HELPER(rebuild_hflags_a64)(CPUARMState *env, int el) +{ + int fp_el = fp_exception_el(env, el); + ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); + + env->hflags = rebuild_hflags_a64(env, el, fp_el, mmu_idx); +} + void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *pflags) { -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> Begin setting, but not relying upon, env->hflags. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-17-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- linux-user/syscall.c | 1 + target/arm/cpu.c | 1 + target/arm/helper-a64.c | 3 +++ target/arm/helper.c | 2 ++ target/arm/machine.c | 1 + target/arm/op_helper.c | 1 + 6 files changed, 9 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -XXX,XX +XXX,XX @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, aarch64_sve_narrow_vq(env, vq); } env->vfp.zcr_el[1] = vq - 1; + arm_rebuild_hflags(env); ret = vq * 16; } return ret; diff --git a/target/arm/cpu.c b/target/arm/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s) hw_breakpoint_update_all(cpu); hw_watchpoint_update_all(cpu); + arm_rebuild_hflags(env); } bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request) diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper-a64.c +++ b/target/arm/helper-a64.c @@ -XXX,XX +XXX,XX @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc) } else { env->regs[15] = new_pc & ~0x3; } + helper_rebuild_hflags_a32(env, new_el); qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to " "AArch32 EL%d PC 0x%" PRIx32 "\n", cur_el, new_el, env->regs[15]); @@ -XXX,XX +XXX,XX @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc) } aarch64_restore_sp(env, new_el); env->pc = new_pc; + helper_rebuild_hflags_a64(env, new_el); qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to " "AArch64 EL%d PC 0x%" PRIx64 "\n", cur_el, new_el, env->pc); } + /* * Note that cur_el can never be 0. If new_el is 0, then * el0_a64 is return_to_aa64, else el0_a64 is ignored. diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ static void take_aarch32_exception(CPUARMState *env, int new_mode, env->regs[14] = env->regs[15] + offset; } env->regs[15] = newpc; + arm_rebuild_hflags(env); } static void arm_cpu_do_interrupt_aarch32_hyp(CPUState *cs) @@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs) pstate_write(env, PSTATE_DAIF | new_mode); env->aarch64 = 1; aarch64_restore_sp(env, new_el); + helper_rebuild_hflags_a64(env, new_el); env->pc = addr; diff --git a/target/arm/machine.c b/target/arm/machine.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/machine.c +++ b/target/arm/machine.c @@ -XXX,XX +XXX,XX @@ static int cpu_post_load(void *opaque, int version_id) if (!kvm_enabled()) { pmu_op_finish(&cpu->env); } + arm_rebuild_hflags(&cpu->env); return 0; } diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -XXX,XX +XXX,XX @@ void HELPER(cpsr_write_eret)(CPUARMState *env, uint32_t val) * state. Do the masking now. */ env->regs[15] &= (env->thumb ? ~1 : ~3); + arm_rebuild_hflags(env); qemu_mutex_lock_iothread(); arm_call_el_change_hook(env_archcpu(env)); -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> Continue setting, but not relying upon, env->hflags. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-18-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/translate-a64.c | 13 +++++++++++-- target/arm/translate.c | 28 +++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread, if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) { /* I/O operations must end the TB here (whether read or write) */ s->base.is_jmp = DISAS_UPDATE; - } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) { - /* We default to ending the TB on a coprocessor register write, + } + if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) { + /* + * A write to any coprocessor regiser that ends a TB + * must rebuild the hflags for the next TB. + */ + TCGv_i32 tcg_el = tcg_const_i32(s->current_el); + gen_helper_rebuild_hflags_a64(cpu_env, tcg_el); + tcg_temp_free_i32(tcg_el); + /* + * We default to ending the TB on a coprocessor register write, * but allow this to be suppressed by the register definition * (usually only necessary to work around guest bugs). */ diff --git a/target/arm/translate.c b/target/arm/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -XXX,XX +XXX,XX @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn) ri = get_arm_cp_reginfo(s->cp_regs, ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2)); if (ri) { + bool need_exit_tb; + /* Check access permissions */ if (!cp_access_ok(s->current_el, ri, isread)) { return 1; @@ -XXX,XX +XXX,XX @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn) } } - if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) { - /* I/O operations must end the TB here (whether read or write) */ - gen_lookup_tb(s); - } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) { - /* We default to ending the TB on a coprocessor register write, + /* I/O operations must end the TB here (whether read or write) */ + need_exit_tb = ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && + (ri->type & ARM_CP_IO)); + + if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) { + /* + * A write to any coprocessor regiser that ends a TB + * must rebuild the hflags for the next TB. + */ + TCGv_i32 tcg_el = tcg_const_i32(s->current_el); + if (arm_dc_feature(s, ARM_FEATURE_M)) { + gen_helper_rebuild_hflags_m32(cpu_env, tcg_el); + } else { + gen_helper_rebuild_hflags_a32(cpu_env, tcg_el); + } + tcg_temp_free_i32(tcg_el); + /* + * We default to ending the TB on a coprocessor register write, * but allow this to be suppressed by the register definition * (usually only necessary to work around guest bugs). */ + need_exit_tb = true; + } + if (need_exit_tb) { gen_lookup_tb(s); } -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> Continue setting, but not relying upon, env->hflags. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-19-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/op_helper.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -XXX,XX +XXX,XX @@ uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift) void HELPER(setend)(CPUARMState *env) { env->uncached_cpsr ^= CPSR_E; + arm_rebuild_hflags(env); } /* Function checks whether WFx (WFI/WFE) instructions are set up to be trapped. @@ -XXX,XX +XXX,XX @@ uint32_t HELPER(cpsr_read)(CPUARMState *env) void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask) { cpsr_write(env, val, mask, CPSRWriteByInstr); + /* TODO: Not all cpsr bits are relevant to hflags. */ + arm_rebuild_hflags(env); } /* Write the CPSR for a 32-bit exception return */ -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> Continue setting, but not relying upon, env->hflags. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-20-richard.henderson@linaro.org Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, /* ??? Lots of these bits are not implemented. */ /* This may enable/disable the MMU, so do a TLB flush. */ tlb_flush(CPU(cpu)); + + if (ri->type & ARM_CP_SUPPRESS_TB_END) { + /* + * Normally we would always end the TB on an SCTLR write; see the + * comment in ARMCPRegInfo sctlr initialization below for why Xscale + * is special. Setting ARM_CP_SUPPRESS_TB_END also stops the rebuild + * of hflags from the translator, so do it here. + */ + arm_rebuild_hflags(env); + } } static CPAccessResult fpexc32_access(CPUARMState *env, const ARMCPRegInfo *ri, -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> Continue setting, but not relying upon, env->hflags. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-21-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/m_helper.c | 6 ++++++ target/arm/translate.c | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/m_helper.c +++ b/target/arm/m_helper.c @@ -XXX,XX +XXX,XX @@ void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest) switch_v7m_security_state(env, dest & 1); env->thumb = 1; env->regs[15] = dest & ~1; + arm_rebuild_hflags(env); } void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest) @@ -XXX,XX +XXX,XX @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest) switch_v7m_security_state(env, 0); env->thumb = 1; env->regs[15] = dest; + arm_rebuild_hflags(env); } static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode, @@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain, env->regs[14] = lr; env->regs[15] = addr & 0xfffffffe; env->thumb = addr & 1; + arm_rebuild_hflags(env); } static void v7m_update_fpccr(CPUARMState *env, uint32_t frameptr, @@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu) /* Otherwise, we have a successful exception exit. */ arm_clear_exclusive(env); + arm_rebuild_hflags(env); qemu_log_mask(CPU_LOG_INT, "...successful exception return\n"); } @@ -XXX,XX +XXX,XX @@ static bool do_v7m_function_return(ARMCPU *cpu) xpsr_write(env, 0, XPSR_IT); env->thumb = newpc & 1; env->regs[15] = newpc & ~1; + arm_rebuild_hflags(env); qemu_log_mask(CPU_LOG_INT, "...function return successful\n"); return true; @@ -XXX,XX +XXX,XX @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu) switch_v7m_security_state(env, true); xpsr_write(env, 0, XPSR_IT); env->regs[15] += 4; + arm_rebuild_hflags(env); return true; gen_invep: diff --git a/target/arm/translate.c b/target/arm/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -XXX,XX +XXX,XX @@ static bool trans_MRS_v7m(DisasContext *s, arg_MRS_v7m *a) static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a) { - TCGv_i32 addr, reg; + TCGv_i32 addr, reg, el; if (!arm_dc_feature(s, ARM_FEATURE_M)) { return false; @@ -XXX,XX +XXX,XX @@ static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a) gen_helper_v7m_msr(cpu_env, addr, reg); tcg_temp_free_i32(addr); tcg_temp_free_i32(reg); + el = tcg_const_i32(s->current_el); + gen_helper_rebuild_hflags_m32(cpu_env, el); + tcg_temp_free_i32(el); gen_lookup_tb(s); return true; } -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> Continue setting, but not relying upon, env->hflags. Suggested-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-22-richard.henderson@linaro.org Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/intc/armv7m_nvic.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index XXXXXXX..XXXXXXX 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr, } } nvic_irq_update(s); - return MEMTX_OK; + goto exit_ok; case 0x200 ... 0x23f: /* NVIC Set pend */ /* the special logic in armv7m_nvic_set_pending() * is not needed since IRQs are never escalated @@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr, } } nvic_irq_update(s); - return MEMTX_OK; + goto exit_ok; case 0x300 ... 0x33f: /* NVIC Active */ - return MEMTX_OK; /* R/O */ + goto exit_ok; /* R/O */ case 0x400 ... 0x5ef: /* NVIC Priority */ startvec = (offset - 0x400) + NVIC_FIRST_IRQ; /* vector # */ @@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr, } } nvic_irq_update(s); - return MEMTX_OK; + goto exit_ok; case 0xd18 ... 0xd1b: /* System Handler Priority (SHPR1) */ if (!arm_feature(&s->cpu->env, ARM_FEATURE_M_MAIN)) { - return MEMTX_OK; + goto exit_ok; } /* fall through */ case 0xd1c ... 0xd23: /* System Handler Priority (SHPR2, SHPR3) */ @@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr, set_prio(s, hdlidx, sbank, newprio); } nvic_irq_update(s); - return MEMTX_OK; + goto exit_ok; case 0xd28 ... 0xd2b: /* Configurable Fault Status (CFSR) */ if (!arm_feature(&s->cpu->env, ARM_FEATURE_M_MAIN)) { - return MEMTX_OK; + goto exit_ok; } /* All bits are W1C, so construct 32 bit value with 0s in * the parts not written by the access size @@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr, */ s->cpu->env.v7m.cfsr[M_REG_NS] &= ~(value & R_V7M_CFSR_BFSR_MASK); } - return MEMTX_OK; + goto exit_ok; } if (size == 4) { nvic_writel(s, offset, value, attrs); - return MEMTX_OK; + goto exit_ok; } qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad write of size %d at offset 0x%x\n", size, offset); /* This is UNPREDICTABLE; treat as RAZ/WI */ + + exit_ok: + /* Ensure any changes made are reflected in the cached hflags. */ + arm_rebuild_hflags(&s->cpu->env); return MEMTX_OK; } -- 2.20.1
From: Richard Henderson <richard.henderson@linaro.org> This is the payoff. From perf record -g data of ubuntu 18 boot and shutdown: BEFORE: - 23.02% 2.82% qemu-system-aar [.] helper_lookup_tb_ptr - 20.22% helper_lookup_tb_ptr + 10.05% tb_htable_lookup - 9.13% cpu_get_tb_cpu_state 3.20% aa64_va_parameters_both 0.55% fp_exception_el - 11.66% 4.74% qemu-system-aar [.] cpu_get_tb_cpu_state - 6.96% cpu_get_tb_cpu_state 3.63% aa64_va_parameters_both 0.60% fp_exception_el 0.53% sve_exception_el AFTER: - 16.40% 3.40% qemu-system-aar [.] helper_lookup_tb_ptr - 13.03% helper_lookup_tb_ptr + 11.19% tb_htable_lookup 0.55% cpu_get_tb_cpu_state 0.98% 0.71% qemu-system-aar [.] cpu_get_tb_cpu_state 0.87% 0.24% qemu-system-aar [.] rebuild_hflags_a64 Before, helper_lookup_tb_ptr is the second hottest function in the application, consuming almost a quarter of the runtime. Within the entire execution, cpu_get_tb_cpu_state consumes about 12%. After, helper_lookup_tb_ptr has dropped to the fourth hottest function, with consumption dropping to a sixth of the runtime. Within the entire execution, cpu_get_tb_cpu_state has dropped below 1%, and the supporting function to rebuild hflags also consumes about 1%. Assertions are retained for --enable-debug-tcg. Tested-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191018174431.1784-23-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ void HELPER(rebuild_hflags_a64)(CPUARMState *env, int el) void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *pflags) { - uint32_t flags, pstate_for_ss; + uint32_t flags = env->hflags; + uint32_t pstate_for_ss; *cs_base = 0; - flags = rebuild_hflags_internal(env); +#ifdef CONFIG_DEBUG_TCG + assert(flags == rebuild_hflags_internal(env)); +#endif - if (is_a64(env)) { + if (FIELD_EX32(flags, TBFLAG_ANY, AARCH64_STATE)) { *pc = env->pc; if (cpu_isar_feature(aa64_bti, env_archcpu(env))) { flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype); -- 2.20.1
From: Philippe Mathieu-Daudé <f4bug@amsat.org> This file keeps the various QDev blocks separated by comments. Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Cleber Rosa <crosa@redhat.com> Message-id: 20191005154748.21718-3-f4bug@amsat.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/sd/sdhci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index XXXXXXX..XXXXXXX 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -XXX,XX +XXX,XX @@ static const TypeInfo sdhci_bus_info = { .class_init = sdhci_bus_class_init, }; +/* --- qdev i.MX eSDHC --- */ + static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size) { SDHCIState *s = SYSBUS_SDHCI(opaque); @@ -XXX,XX +XXX,XX @@ usdhc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) } } - static const MemoryRegionOps usdhc_mmio_ops = { .read = usdhc_read, .write = usdhc_write, -- 2.20.1
From: Philippe Mathieu-Daudé <f4bug@amsat.org> The Linux kernel access few S3C-specific registers [1] to set some clock. We don't care about this part for device emulation [2]. Add a dummy device to properly ignore these accesses, so we can focus on the important registers missing. [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/mmc/host/sdhci-s3c-regs.h?h=cc014f3 [2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/mmc/host/sdhci-s3c.c?h=v5.3#n263 Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org> Message-id: 20191005154748.21718-4-f4bug@amsat.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- include/hw/sd/sdhci.h | 2 ++ hw/sd/sdhci.c | 65 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/sd/sdhci.h +++ b/include/hw/sd/sdhci.h @@ -XXX,XX +XXX,XX @@ typedef struct SDHCIState { #define TYPE_IMX_USDHC "imx-usdhc" +#define TYPE_S3C_SDHCI "s3c-sdhci" + #endif /* SDHCI_H */ diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index XXXXXXX..XXXXXXX 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -XXX,XX +XXX,XX @@ static const TypeInfo imx_usdhc_info = { .instance_init = imx_usdhc_init, }; +/* --- qdev Samsung s3c --- */ + +#define S3C_SDHCI_CONTROL2 0x80 +#define S3C_SDHCI_CONTROL3 0x84 +#define S3C_SDHCI_CONTROL4 0x8c + +static uint64_t sdhci_s3c_read(void *opaque, hwaddr offset, unsigned size) +{ + uint64_t ret; + + switch (offset) { + case S3C_SDHCI_CONTROL2: + case S3C_SDHCI_CONTROL3: + case S3C_SDHCI_CONTROL4: + /* ignore */ + ret = 0; + break; + default: + ret = sdhci_read(opaque, offset, size); + break; + } + + return ret; +} + +static void sdhci_s3c_write(void *opaque, hwaddr offset, uint64_t val, + unsigned size) +{ + switch (offset) { + case S3C_SDHCI_CONTROL2: + case S3C_SDHCI_CONTROL3: + case S3C_SDHCI_CONTROL4: + /* ignore */ + break; + default: + sdhci_write(opaque, offset, val, size); + break; + } +} + +static const MemoryRegionOps sdhci_s3c_mmio_ops = { + .read = sdhci_s3c_read, + .write = sdhci_s3c_write, + .valid = { + .min_access_size = 1, + .max_access_size = 4, + .unaligned = false + }, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void sdhci_s3c_init(Object *obj) +{ + SDHCIState *s = SYSBUS_SDHCI(obj); + + s->io_ops = &sdhci_s3c_mmio_ops; +} + +static const TypeInfo sdhci_s3c_info = { + .name = TYPE_S3C_SDHCI , + .parent = TYPE_SYSBUS_SDHCI, + .instance_init = sdhci_s3c_init, +}; + static void sdhci_register_types(void) { type_register_static(&sdhci_sysbus_info); type_register_static(&sdhci_bus_info); type_register_static(&imx_usdhc_info); + type_register_static(&sdhci_s3c_info); } type_init(sdhci_register_types) -- 2.20.1
From: Philippe Mathieu-Daudé <f4bug@amsat.org> The Exynos SoC has specific SDHCI registers. Use the s3c SDHCI model which handle these specific registers. This silents the following "SDHC ... not implemented" warnings so we can focus on the important registers missing: $ qemu-system-arm ... -d unimp \ -append "... root=/dev/mmcblk0 rootfstype=ext4 rw rootwait" \ -drive file=linux-build-test/rootfs/arm/rootfs-armv5.ext2,if=sd,format=raw [...] [ 25.744858] sdhci: Secure Digital Host Controller Interface driver [ 25.745862] sdhci: Copyright(c) Pierre Ossman [ 25.783188] s3c-sdhci 12530000.sdhci: clock source 2: mmc_busclk.2 (12000000 Hz) SDHC rd_4b @0x80 not implemented SDHC wr_4b @0x80 <- 0x00000020 not implemented SDHC wr_4b @0x8c <- 0x00030000 not implemented SDHC rd_4b @0x80 not implemented SDHC wr_4b @0x80 <- 0xc0004100 not implemented SDHC wr_4b @0x84 <- 0x80808080 not implemented [ 26.013318] mmc0: SDHCI controller on samsung-hsmmc [12530000.sdhci] using ADMA [ 26.032318] Synopsys Designware Multimedia Card Interface Driver [ 42.024885] Waiting for root device /dev/mmcblk0... Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org> Message-id: 20191005154748.21718-5-f4bug@amsat.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/arm/exynos4210.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/exynos4210.c +++ b/hw/arm/exynos4210.c @@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp) * public datasheet which is very similar (implementing * MMC Specification Version 4.0 being the only difference noted) */ - dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI); + dev = qdev_create(NULL, TYPE_S3C_SDHCI); qdev_prop_set_uint64(dev, "capareg", EXYNOS4210_SDHCI_CAPABILITIES); qdev_init_nofail(dev); -- 2.20.1
From: Philippe Mathieu-Daudé <philmd@redhat.com> IEC binary prefixes ease code review: the unit is explicit. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-id: 20191021190653.9511-2-philmd@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/arm/xilinx_zynq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/xilinx_zynq.c +++ b/hw/arm/xilinx_zynq.c @@ -XXX,XX +XXX,XX @@ */ #include "qemu/osdep.h" +#include "qemu/units.h" #include "qapi/error.h" #include "cpu.h" #include "hw/sysbus.h" @@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine) memory_region_add_subregion(address_space_mem, 0, ext_ram); /* 256K of on-chip memory */ - memory_region_init_ram(ocm_ram, NULL, "zynq.ocm_ram", 256 << 10, + memory_region_init_ram(ocm_ram, NULL, "zynq.ocm_ram", 256 * KiB, &error_fatal); memory_region_add_subregion(address_space_mem, 0xFFFC0000, ocm_ram); -- 2.20.1
From: Philippe Mathieu-Daudé <philmd@redhat.com> IEC binary prefixes ease code review: the unit is explicit. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-id: 20191021190653.9511-3-philmd@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/arm/mps2-tz.c | 3 ++- hw/arm/mps2.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/mps2-tz.c +++ b/hw/arm/mps2-tz.c @@ -XXX,XX +XXX,XX @@ */ #include "qemu/osdep.h" +#include "qemu/units.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "hw/arm/boot.h" @@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine) * call the 16MB our "system memory", as it's the largest lump. */ memory_region_allocate_system_memory(&mms->psram, - NULL, "mps.ram", 0x01000000); + NULL, "mps.ram", 16 * MiB); memory_region_add_subregion(system_memory, 0x80000000, &mms->psram); /* The overflow IRQs for all UARTs are ORed together. diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/mps2.c +++ b/hw/arm/mps2.c @@ -XXX,XX +XXX,XX @@ */ #include "qemu/osdep.h" +#include "qemu/units.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "hw/arm/boot.h" @@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine) * zbt_boot_ctrl is always zero). */ memory_region_allocate_system_memory(&mms->psram, - NULL, "mps.ram", 0x1000000); + NULL, "mps.ram", 16 * MiB); memory_region_add_subregion(system_memory, 0x21000000, &mms->psram); switch (mmc->fpga_type) { -- 2.20.1
From: Philippe Mathieu-Daudé <philmd@redhat.com> The SDRAM is incorrectly created in the SA1110 SoC. Move its creation in the board code, this will later allow the board to have the QOM ownership of the RAM. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-id: 20191021190653.9511-4-philmd@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/arm/strongarm.h | 4 +--- hw/arm/collie.c | 8 ++++++-- hw/arm/strongarm.c | 7 +------ 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/hw/arm/strongarm.h b/hw/arm/strongarm.h index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/strongarm.h +++ b/hw/arm/strongarm.h @@ -XXX,XX +XXX,XX @@ enum { typedef struct { ARMCPU *cpu; - MemoryRegion sdram; DeviceState *pic; DeviceState *gpio; DeviceState *ppc; @@ -XXX,XX +XXX,XX @@ typedef struct { SSIBus *ssp_bus; } StrongARMState; -StrongARMState *sa1110_init(MemoryRegion *sysmem, - unsigned int sdram_size, const char *rev); +StrongARMState *sa1110_init(const char *cpu_type); #endif diff --git a/hw/arm/collie.c b/hw/arm/collie.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/collie.c +++ b/hw/arm/collie.c @@ -XXX,XX +XXX,XX @@ static void collie_init(MachineState *machine) { StrongARMState *s; DriveInfo *dinfo; - MemoryRegion *sysmem = get_system_memory(); + MemoryRegion *sdram = g_new(MemoryRegion, 1); - s = sa1110_init(sysmem, collie_binfo.ram_size, machine->cpu_type); + s = sa1110_init(machine->cpu_type); + + memory_region_allocate_system_memory(sdram, NULL, "strongarm.sdram", + collie_binfo.ram_size); + memory_region_add_subregion(get_system_memory(), SA_SDCS0, sdram); dinfo = drive_get(IF_PFLASH, 0, 0); pflash_cfi01_register(SA_CS0, "collie.fl1", 0x02000000, diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/strongarm.c +++ b/hw/arm/strongarm.c @@ -XXX,XX +XXX,XX @@ static const TypeInfo strongarm_ssp_info = { }; /* Main CPU functions */ -StrongARMState *sa1110_init(MemoryRegion *sysmem, - unsigned int sdram_size, const char *cpu_type) +StrongARMState *sa1110_init(const char *cpu_type) { StrongARMState *s; int i; @@ -XXX,XX +XXX,XX @@ StrongARMState *sa1110_init(MemoryRegion *sysmem, s->cpu = ARM_CPU(cpu_create(cpu_type)); - memory_region_allocate_system_memory(&s->sdram, NULL, "strongarm.sdram", - sdram_size); - memory_region_add_subregion(sysmem, SA_SDCS0, &s->sdram); - s->pic = sysbus_create_varargs("strongarm_pic", 0x90050000, qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ), qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ), -- 2.20.1
From: Philippe Mathieu-Daudé <philmd@redhat.com> The SDRAM is incorrectly created in the OMAP2420 SoC. Move its creation in the board code, this will later allow the board to have the QOM ownership of the RAM. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-id: 20191021190653.9511-5-philmd@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- include/hw/arm/omap.h | 4 +--- hw/arm/nseries.c | 10 +++++++--- hw/arm/omap2.c | 13 +++++-------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/omap.h +++ b/include/hw/arm/omap.h @@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s { MemoryRegion tap_iomem; MemoryRegion imif_ram; MemoryRegion emiff_ram; - MemoryRegion sdram; MemoryRegion sram; struct omap_dma_port_if_s { @@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory, const char *core); /* omap2.c */ -struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem, - unsigned long sdram_size, +struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sdram, const char *core); uint32_t omap_badwidth_read8(void *opaque, hwaddr addr); diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/nseries.c +++ b/hw/arm/nseries.c @@ -XXX,XX +XXX,XX @@ /* Nokia N8x0 support */ struct n800_s { + MemoryRegion sdram; struct omap_mpu_state_s *mpu; struct rfbi_chip_s blizzard; @@ -XXX,XX +XXX,XX @@ static int n810_atag_setup(const struct arm_boot_info *info, void *p) static void n8x0_init(MachineState *machine, struct arm_boot_info *binfo, int model) { - MemoryRegion *sysmem = get_system_memory(); struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s)); - int sdram_size = binfo->ram_size; + uint64_t sdram_size = binfo->ram_size; - s->mpu = omap2420_mpu_init(sysmem, sdram_size, machine->cpu_type); + memory_region_allocate_system_memory(&s->sdram, NULL, "omap2.dram", + sdram_size); + memory_region_add_subregion(get_system_memory(), OMAP2_Q2_BASE, &s->sdram); + + s->mpu = omap2420_mpu_init(&s->sdram, machine->cpu_type); /* Setup peripherals * diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/omap2.c +++ b/hw/arm/omap2.c @@ -XXX,XX +XXX,XX @@ #include "qemu/error-report.h" #include "qapi/error.h" #include "cpu.h" +#include "exec/address-spaces.h" #include "sysemu/blockdev.h" #include "sysemu/qtest.h" #include "sysemu/reset.h" @@ -XXX,XX +XXX,XX @@ static const struct dma_irq_map omap2_dma_irq_map[] = { { 0, OMAP_INT_24XX_SDMA_IRQ3 }, }; -struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem, - unsigned long sdram_size, +struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sdram, const char *cpu_type) { struct omap_mpu_state_s *s = g_new0(struct omap_mpu_state_s, 1); @@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem, int i; SysBusDevice *busdev; struct omap_target_agent_s *ta; + MemoryRegion *sysmem = get_system_memory(); /* Core */ s->mpu_model = omap2420; s->cpu = ARM_CPU(cpu_create(cpu_type)); - s->sdram_size = sdram_size; s->sram_size = OMAP242X_SRAM_SIZE; s->wakeup = qemu_allocate_irq(omap_mpu_wakeup, s, 0); @@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem, omap_clk_init(s); /* Memory-mapped stuff */ - memory_region_allocate_system_memory(&s->sdram, NULL, "omap2.dram", - s->sdram_size); - memory_region_add_subregion(sysmem, OMAP2_Q2_BASE, &s->sdram); memory_region_init_ram(&s->sram, NULL, "omap2.sram", s->sram_size, &error_fatal); memory_region_add_subregion(sysmem, OMAP2_SRAM_BASE, &s->sram); @@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem, s->port->addr_valid = omap2_validate_addr; /* Register SDRAM and SRAM ports for fast DMA transfers. */ - soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sdram), - OMAP2_Q2_BASE, s->sdram_size); + soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(sdram), + OMAP2_Q2_BASE, memory_region_size(sdram)); soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sram), OMAP2_SRAM_BASE, s->sram_size); -- 2.20.1
From: Philippe Mathieu-Daudé <philmd@redhat.com> The SDRAM is incorrectly created in the OMAP310 SoC. Move its creation in the board code, this will later allow the board to have the QOM ownership of the RAM. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-id: 20191021190653.9511-6-philmd@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- include/hw/arm/omap.h | 6 ++---- hw/arm/omap1.c | 12 +++++------- hw/arm/omap_sx1.c | 8 ++++++-- hw/arm/palm.c | 8 ++++++-- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/omap.h +++ b/include/hw/arm/omap.h @@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s { MemoryRegion mpui_io_iomem; MemoryRegion tap_iomem; MemoryRegion imif_ram; - MemoryRegion emiff_ram; MemoryRegion sram; struct omap_dma_port_if_s { @@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s { hwaddr addr); } port[__omap_dma_port_last]; - unsigned long sdram_size; + uint64_t sdram_size; unsigned long sram_size; /* MPUI-TIPB peripherals */ @@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s { }; /* omap1.c */ -struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory, - unsigned long sdram_size, +struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *sdram, const char *core); /* omap2.c */ diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/omap1.c +++ b/hw/arm/omap1.c @@ -XXX,XX +XXX,XX @@ #include "qapi/error.h" #include "qemu-common.h" #include "cpu.h" +#include "exec/address-spaces.h" #include "hw/boards.h" #include "hw/hw.h" #include "hw/irq.h" @@ -XXX,XX +XXX,XX @@ static int omap_validate_tipb_mpui_addr(struct omap_mpu_state_s *s, return range_covers_byte(0xe1010000, 0xe1020004 - 0xe1010000, addr); } -struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory, - unsigned long sdram_size, +struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *dram, const char *cpu_type) { int i; @@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory, qemu_irq dma_irqs[6]; DriveInfo *dinfo; SysBusDevice *busdev; + MemoryRegion *system_memory = get_system_memory(); /* Core */ s->mpu_model = omap310; s->cpu = ARM_CPU(cpu_create(cpu_type)); - s->sdram_size = sdram_size; + s->sdram_size = memory_region_size(dram); s->sram_size = OMAP15XX_SRAM_SIZE; s->wakeup = qemu_allocate_irq(omap_mpu_wakeup, s, 0); @@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory, omap_clk_init(s); /* Memory-mapped stuff */ - memory_region_allocate_system_memory(&s->emiff_ram, NULL, "omap1.dram", - s->sdram_size); - memory_region_add_subregion(system_memory, OMAP_EMIFF_BASE, &s->emiff_ram); memory_region_init_ram(&s->imif_ram, NULL, "omap1.sram", s->sram_size, &error_fatal); memory_region_add_subregion(system_memory, OMAP_IMIF_BASE, &s->imif_ram); @@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory, s->port[tipb_mpui].addr_valid = omap_validate_tipb_mpui_addr; /* Register SDRAM and SRAM DMA ports for fast transfers. */ - soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->emiff_ram), + soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(dram), OMAP_EMIFF_BASE, s->sdram_size); soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->imif_ram), OMAP_IMIF_BASE, s->sram_size); diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/omap_sx1.c +++ b/hw/arm/omap_sx1.c @@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version) { struct omap_mpu_state_s *mpu; MemoryRegion *address_space = get_system_memory(); + MemoryRegion *dram = g_new(MemoryRegion, 1); MemoryRegion *flash = g_new(MemoryRegion, 1); MemoryRegion *cs = g_new(MemoryRegion, 4); static uint32_t cs0val = 0x00213090; @@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version) flash_size = flash2_size; } - mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, - machine->cpu_type); + memory_region_allocate_system_memory(dram, NULL, "omap1.dram", + sx1_binfo.ram_size); + memory_region_add_subregion(address_space, OMAP_EMIFF_BASE, dram); + + mpu = omap310_mpu_init(dram, machine->cpu_type); /* External Flash (EMIFS) */ memory_region_init_ram(flash, NULL, "omap_sx1.flash0-0", flash_size, diff --git a/hw/arm/palm.c b/hw/arm/palm.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/palm.c +++ b/hw/arm/palm.c @@ -XXX,XX +XXX,XX @@ static void palmte_init(MachineState *machine) MemoryRegion *address_space_mem = get_system_memory(); struct omap_mpu_state_s *mpu; int flash_size = 0x00800000; - int sdram_size = palmte_binfo.ram_size; static uint32_t cs0val = 0xffffffff; static uint32_t cs1val = 0x0000e1a0; static uint32_t cs2val = 0x0000e1a0; static uint32_t cs3val = 0xe1a0e1a0; int rom_size, rom_loaded = 0; + MemoryRegion *dram = g_new(MemoryRegion, 1); MemoryRegion *flash = g_new(MemoryRegion, 1); MemoryRegion *cs = g_new(MemoryRegion, 4); - mpu = omap310_mpu_init(address_space_mem, sdram_size, machine->cpu_type); + memory_region_allocate_system_memory(dram, NULL, "omap1.dram", + palmte_binfo.ram_size); + memory_region_add_subregion(address_space_mem, OMAP_EMIFF_BASE, dram); + + mpu = omap310_mpu_init(dram, machine->cpu_type); /* External Flash (EMIFS) */ memory_region_init_ram(flash, NULL, "palmte.flash", flash_size, -- 2.20.1
From: Philippe Mathieu-Daudé <philmd@redhat.com> Having the RAM creation code in a separate function is not very helpful. Move this code directly inside the board_init() function, this will later allow the board to have the QOM ownership of the RAM. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-id: 20191021190653.9511-7-philmd@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/arm/digic_boards.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/hw/arm/digic_boards.c b/hw/arm/digic_boards.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/digic_boards.c +++ b/hw/arm/digic_boards.c @@ -XXX,XX +XXX,XX @@ typedef struct DigicBoard { const char *rom1_def_filename; } DigicBoard; -static void digic4_board_setup_ram(DigicBoardState *s, hwaddr ram_size) -{ - memory_region_allocate_system_memory(&s->ram, NULL, "ram", ram_size); - memory_region_add_subregion(get_system_memory(), 0, &s->ram); -} - static void digic4_board_init(DigicBoard *board) { Error *err = NULL; @@ -XXX,XX +XXX,XX @@ static void digic4_board_init(DigicBoard *board) exit(1); } - digic4_board_setup_ram(s, board->ram_size); + memory_region_allocate_system_memory(&s->ram, NULL, "ram", board->ram_size); + memory_region_add_subregion(get_system_memory(), 0, &s->ram); if (board->add_rom0) { board->add_rom0(s, DIGIC4_ROM0_BASE, board->rom0_def_filename); -- 2.20.1
v3->v4: Windows headers define an INT type which clashed with an enum value name in arm_gicv3_its.c... The following changes since commit eae587e8e3694b1aceab23239493fb4c7e1a80f5: Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-09-13' into staging (2021-09-13 11:00:30 +0100) are available in the Git repository at: https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210913-3 for you to fetch changes up to 28e987a7e7edaa3ca7feeac65edca26145df8814: hw/arm/mps2.c: Mark internal-only I2C buses as 'full' (2021-09-13 21:01:08 +0100) ---------------------------------------------------------------- target-arm queue: * mark MPS2/MPS3 board-internal i2c buses as 'full' so that command line user-created devices are not plugged into them * Take an exception if PSTATE.IL is set * Support an emulated ITS in the virt board * Add support for kudo-bmc board * Probe for KVM_CAP_ARM_VM_IPA_SIZE when creating scratch VM * cadence_uart: Fix clock handling issues that prevented u-boot from running ---------------------------------------------------------------- Bin Meng (6): hw/misc: zynq_slcr: Correctly compute output clocks in the reset exit phase hw/char: cadence_uart: Disable transmit when input clock is disabled hw/char: cadence_uart: Move clock/reset check to uart_can_receive() hw/char: cadence_uart: Convert to memop_with_attrs() ops hw/char: cadence_uart: Ignore access when unclocked or in reset for uart_{read, write}() hw/char: cadence_uart: Log a guest error when device is unclocked or in reset Chris Rauer (1): hw/arm: Add support for kudo-bmc board. Marc Zyngier (1): hw/arm/virt: KVM: Probe for KVM_CAP_ARM_VM_IPA_SIZE when creating scratch VM Peter Maydell (5): target/arm: Take an exception if PSTATE.IL is set qdev: Support marking individual buses as 'full' hw/arm/mps2-tz.c: Add extra data parameter to MakeDevFn hw/arm/mps2-tz.c: Mark internal-only I2C buses as 'full' hw/arm/mps2.c: Mark internal-only I2C buses as 'full' Richard Henderson (1): target/arm: Merge disas_a64_insn into aarch64_tr_translate_insn Shashi Mallela (9): hw/intc: GICv3 ITS initial framework hw/intc: GICv3 ITS register definitions added hw/intc: GICv3 ITS command queue framework hw/intc: GICv3 ITS Command processing hw/intc: GICv3 ITS Feature enablement hw/intc: GICv3 redistributor ITS processing tests/data/acpi/virt: Add IORT files for ITS hw/arm/virt: add ITS support in virt GIC tests/data/acpi/virt: Update IORT files for ITS docs/system/arm/nuvoton.rst | 1 + hw/intc/gicv3_internal.h | 188 ++++- include/hw/arm/virt.h | 2 + include/hw/intc/arm_gicv3_common.h | 13 + include/hw/intc/arm_gicv3_its_common.h | 32 +- include/hw/qdev-core.h | 24 + target/arm/cpu.h | 1 + target/arm/kvm_arm.h | 4 +- target/arm/syndrome.h | 5 + target/arm/translate.h | 2 + hw/arm/mps2-tz.c | 92 ++- hw/arm/mps2.c | 12 +- hw/arm/npcm7xx_boards.c | 34 + hw/arm/virt.c | 29 +- hw/char/cadence_uart.c | 61 +- hw/intc/arm_gicv3.c | 14 + hw/intc/arm_gicv3_common.c | 13 + hw/intc/arm_gicv3_cpuif.c | 7 +- hw/intc/arm_gicv3_dist.c | 5 +- hw/intc/arm_gicv3_its.c | 1322 ++++++++++++++++++++++++++++++++ hw/intc/arm_gicv3_its_common.c | 7 +- hw/intc/arm_gicv3_its_kvm.c | 2 +- hw/intc/arm_gicv3_redist.c | 153 +++- hw/misc/zynq_slcr.c | 31 +- softmmu/qdev-monitor.c | 7 +- target/arm/helper-a64.c | 1 + target/arm/helper.c | 8 + target/arm/kvm.c | 7 +- target/arm/translate-a64.c | 255 +++--- target/arm/translate.c | 21 + hw/intc/meson.build | 1 + tests/data/acpi/virt/IORT | Bin 0 -> 124 bytes tests/data/acpi/virt/IORT.memhp | Bin 0 -> 124 bytes tests/data/acpi/virt/IORT.numamem | Bin 0 -> 124 bytes tests/data/acpi/virt/IORT.pxb | Bin 0 -> 124 bytes 35 files changed, 2144 insertions(+), 210 deletions(-) create mode 100644 hw/intc/arm_gicv3_its.c create mode 100644 tests/data/acpi/virt/IORT create mode 100644 tests/data/acpi/virt/IORT.memhp create mode 100644 tests/data/acpi/virt/IORT.numamem create mode 100644 tests/data/acpi/virt/IORT.pxb