:p
atchew
Login
Hi; here's another arm pullreq. This one has in it some bugfix/cleanup/refactoring bits and pieces from me, and the first third of Richard's FP8 emulation work. thanks -- PMM The following changes since commit cbf877d67a812be17a9ce404a589e1bdf722c1f6: Merge tag 'pbouvier/pr/docs-20260522' of https://gitlab.com/p-b-o/qemu into staging (2026-05-24 07:45:19 -0400) are available in the Git repository at: https://gitlab.com/pm215/qemu.git tags/pull-target-arm-20260526 for you to fetch changes up to 1574211d1fd2052e90ede8865901c48fb391b132: target/arm: Move vectors_overlap to vec_internal.h (2026-05-26 11:41:00 +0100) ---------------------------------------------------------------- target-arm queue: * hw/timer/mss_timer: Remove dead code in timer_write() * OMAP: Remove various pieces of dead code * target/arm: Set debug in attrs in translate_for_debug() * target/arm/ptw: Flip sense of get_phys_addr_* return values * tests/functional/aarch64: Bump up timeout on vbsa * target/arm: Fix minor FEAT_AFP corner case bugs * target/arm: Implement FEAT_FAMINMAX * target/arm: Implement FEAT_FPMR * target/arm: Some initial patches towards other FP8 features ---------------------------------------------------------------- Peter Maydell (31): hw/timer/mss_timer: Remove dead code in timer_write() hw/arm/omap: Remove omap_mpu_model remnants hw/arm/omap: Remove unused omap_mpuio functions hw/arm/omap: Remove stray unused prototype hw/arm/omap: Remove unused omap1_dma_irq_map[] entries hw/arm/omap: Delete unused #defines hw/arm/omap: Remove unused wakeup irq hw/dma/omap_dma: Remove support for dma_3_0 and dma_3_2 hw/dma/omap_dma: Fold omap_dma_sys_read() and omap_dma_sys_write() into callers hw/dma/omap_dma: Remove omap_3_1_compatible_disable flag hw/dma/omap_dma: Remove 3.1 mapping handling hw/dma/omap_dma: Drop model argument to omap_dma_init() target/arm: Set debug in attrs in translate_for_debug() target/arm/ptw: Flip sense of get_phys_addr_disabled return value target/arm/ptw: Flip sense of get_phys_addr_lpae return value target/arm/ptw: Flip sense of get_phys_addr_v6 return value target/arm/ptw: Flip sense of get_phys_addr_v5 return value target/arm/ptw: Flip sense of get_phys_addr_psmav5 return value target/arm/ptw: Flip sense of get_phys_addr_pmsav7 return value target/arm/ptw: Flip sense of get_phys_addr_pmsav8 return value target/arm/ptw: Flip sense of pmsav8_mpu_lookup return value target/arm/ptw: Flip sense of get_phys_addr_twostage return value target/arm/ptw: Flip sense of get_phys_addr_nogpc return value target/arm/ptw: Flip sense of get_phys_addr_gpc return value target/arm/ptw: Flip sense of arm_cpu_get_phys_addr return value target/arm/ptw: Flip sense of get_phys_addr_for_at return value target/arm/ptw: Flip sense of get_phys_addr return value tests/functional/aarch64: Bump up timeout on vbsa target/arm: SVE2 FMAXP, FMINP must honour AH=1 target/arm: Use FPST_A64_F16 for SVE FCVTLT_hs target/arm: Set correct fp flags for FLOGB when FPCR.AH = 1 Pierrick Bouvier (1): tests/functional/aarch64/rme: update images to support FEAT_FP8 Richard Henderson (22): target/arm: Implement ID_AA64ISAR3 target/arm: Implement FEAT_FAMINMAX for AdvSIMD target/arm: Implement FEAT_FAMINMAX for SME target/arm: Implement FEAT_FAMINMAX for SVE target/arm: Enable FEAT_FAMINMAX for -cpu max target/arm: Update SCR bits for Arm ARM M.a.a target/arm: Update HCRX bits for Arm ARM M.a.a target/arm: Introduce FPMR target/arm: Update SCTLR bits for FEAT_FPMR target/arm: Enable EnFPM bits for FEAT_FPMR target/arm: Clear FPMR on ResetSVEState target/arm: Add FPMR_EL to TBFLAGS target/arm: Trap direct acceses to FPMR target/arm: Dump FPMR when present linux-user/aarch64: Implement FPMR signal frames target/arm: Enable FEAT_FPMR for -cpu max target/arm: Implement ID_AA64FPFR0 target/arm: Add isar_feature_aa64_f8cvt target/arm: Implement FSCALE for AdvSIMD target/arm: Implement FSCALE for SME target/arm: Split vector-type.h from cpu.h target/arm: Move vectors_overlap to vec_internal.h docs/system/arm/emulation.rst | 2 + hw/arm/omap1.c | 84 +--- hw/dma/omap_dma.c | 584 +++------------------------ hw/gpio/omap_gpio.c | 6 - hw/misc/omap_clk.c | 9 +- hw/timer/mss-timer.c | 13 +- include/hw/arm/omap.h | 252 +----------- linux-user/aarch64/elfload.c | 2 + linux-user/aarch64/signal.c | 44 +- target/arm/cpregs.h | 5 + target/arm/cpu-features.h | 54 +++ target/arm/cpu-sysregs.h.inc | 2 + target/arm/cpu.c | 11 +- target/arm/cpu.h | 52 +-- target/arm/helper.c | 43 +- target/arm/internals.h | 17 +- target/arm/machine.c | 20 + target/arm/ptw.c | 83 ++-- target/arm/tcg/a64.decode | 8 + target/arm/tcg/cpregs-at.c | 12 +- target/arm/tcg/cpu64.c | 8 + target/arm/tcg/helper-a64-defs.h | 11 + target/arm/tcg/helper-sve-defs.h | 28 ++ target/arm/tcg/hflags.c | 42 ++ target/arm/tcg/m_helper.c | 8 +- target/arm/tcg/sme.decode | 11 + target/arm/tcg/sme_helper.c | 6 - target/arm/tcg/sve.decode | 2 + target/arm/tcg/sve_helper.c | 25 +- target/arm/tcg/tlb_helper.c | 6 +- target/arm/tcg/translate-a64.c | 26 ++ target/arm/tcg/translate-sme.c | 38 +- target/arm/tcg/translate-sve.c | 26 +- target/arm/tcg/translate.h | 14 + target/arm/tcg/vec_helper64.c | 42 ++ target/arm/tcg/vec_internal.h | 21 + target/arm/vector-type.h | 44 ++ tests/functional/aarch64/meson.build | 1 + tests/functional/aarch64/test_rme_sbsaref.py | 7 +- tests/functional/aarch64/test_rme_virt.py | 7 +- 40 files changed, 678 insertions(+), 998 deletions(-) create mode 100644 target/arm/vector-type.h
In timer_write(), we switch() on the address offset to handle registers that need special-casing, with a default case that handles both "unsupported (64-bit mode) register" and "can just write value to st->regs[]". However, as Coverity points out, every register is covered by the special-casing, so the "write to st->regs[]" code path is dead. (timer_read() has a similar structure but there several registers do go through the default code path.) Replace the dead code with an assertion. CID: 1613905 Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260512134750.3543639-1-peter.maydell@linaro.org --- hw/timer/mss-timer.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/hw/timer/mss-timer.c b/hw/timer/mss-timer.c index XXXXXXX..XXXXXXX 100644 --- a/hw/timer/mss-timer.c +++ b/hw/timer/mss-timer.c @@ -XXX,XX +XXX,XX @@ timer_write(void *opaque, hwaddr offset, break; default: - if (addr < R_TIM1_MAX) { - st->regs[addr] = value; - } else { - qemu_log_mask(LOG_GUEST_ERROR, - TYPE_MSS_TIMER": 64-bit mode not supported\n"); - return; - } - break; + /* All non-64-bit regs covered by the switch cases */ + assert(addr >= R_TIM1_MAX); + qemu_log_mask(LOG_GUEST_ERROR, + TYPE_MSS_TIMER": 64-bit mode not supported\n"); + return; } timer_update_irq(st); } -- 2.43.0
The omap1.c code has handling for an mpu_model field which is an enum of which OMAP SoC model it is. We removed most of our OMAP support some time ago, and now the only OMAP SoC we implement is the OMAP310, which sets s->mpu_model = omap310 in omap310_mpu_init(). That makes all the handling for other settings of mpu_model dead code; remove them. This includes the omap GPIO device's mpu_model property which we set but which the device makes no use of, and the omap-id-e20 memory region (because the OMAP310 satisfies cpu_is_omap15xx(), so never executed the old if() block). Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260512203414.3633237-2-peter.maydell@linaro.org --- hw/arm/omap1.c | 28 ++-------------------------- hw/gpio/omap_gpio.c | 6 ------ hw/misc/omap_clk.c | 9 +-------- include/hw/arm/omap.h | 18 ------------------ 4 files changed, 3 insertions(+), 58 deletions(-) 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 @@ static void omap_pin_cfg_init(MemoryRegion *system_memory, static uint64_t omap_id_read(void *opaque, hwaddr addr, unsigned size) { - struct omap_mpu_state_s *s = opaque; - if (size != 4) { qemu_log_mask(LOG_GUEST_ERROR, "%s: read at offset 0x%" HWADDR_PRIx " with bad width %d\n", __func__, addr, size); @@ -XXX,XX +XXX,XX @@ static uint64_t omap_id_read(void *opaque, hwaddr addr, return 0xcafeb574; case 0xfffed400: /* JTAG_ID_LSB */ - switch (s->mpu_model) { - case omap310: - return 0x03310315; - case omap1510: - return 0x03310115; - default: - hw_error("%s: bad mpu model\n", __func__); - } - break; + return 0x03310315; /* omap310 */ case 0xfffed404: /* JTAG_ID_MSB */ - switch (s->mpu_model) { - case omap310: - return 0xfb57402f; - case omap1510: - return 0xfb47002f; - default: - hw_error("%s: bad mpu model\n", __func__); - } + return 0xfb57402f; /* omap310 */ break; } @@ -XXX,XX +XXX,XX @@ static void omap_id_init(MemoryRegion *memory, struct omap_mpu_state_s *mpu) memory_region_init_alias(&mpu->id_iomem_ed4, NULL, "omap-id-ed4", &mpu->id_iomem, 0xfffed400, 0x100); memory_region_add_subregion(memory, 0xfffed400, &mpu->id_iomem_ed4); - if (!cpu_is_omap15xx(mpu)) { - memory_region_init_alias(&mpu->id_iomem_ed4, NULL, "omap-id-e20", - &mpu->id_iomem, 0xfffe2000, 0x800); - memory_region_add_subregion(memory, 0xfffe2000, &mpu->id_iomem_e20); - } } /* MPUI Control (Dummy) */ @@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *dram, MemoryRegion *system_memory = get_system_memory(); /* Core */ - s->mpu_model = omap310; s->cpu = ARM_CPU(cpu_create(cpu_type)); s->sdram_size = memory_region_size(dram); s->sram_size = OMAP15XX_SRAM_SIZE; @@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *dram, s->wakeup, omap_findclk(s, "clk32-kHz")); s->gpio = qdev_new("omap-gpio"); - qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model); omap_gpio_set_clk(OMAP1_GPIO(s->gpio), omap_findclk(s, "arm_gpio_ck")); sysbus_realize_and_unref(SYS_BUS_DEVICE(s->gpio), &error_fatal); sysbus_connect_irq(SYS_BUS_DEVICE(s->gpio), 0, diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c index XXXXXXX..XXXXXXX 100644 --- a/hw/gpio/omap_gpio.c +++ b/hw/gpio/omap_gpio.c @@ -XXX,XX +XXX,XX @@ struct Omap1GpioState { SysBusDevice parent_obj; MemoryRegion iomem; - int mpu_model; void *clk; struct omap_gpio_s omap1; }; @@ -XXX,XX +XXX,XX @@ void omap_gpio_set_clk(Omap1GpioState *gpio, omap_clk clk) gpio->clk = clk; } -static const Property omap_gpio_properties[] = { - DEFINE_PROP_INT32("mpu_model", Omap1GpioState, mpu_model, 0), -}; - static void omap_gpio_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = omap_gpio_realize; device_class_set_legacy_reset(dc, omap_gpif_reset); - device_class_set_props(dc, omap_gpio_properties); /* Reason: pointer property "clk" */ dc->user_creatable = false; } diff --git a/hw/misc/omap_clk.c b/hw/misc/omap_clk.c index XXXXXXX..XXXXXXX 100644 --- a/hw/misc/omap_clk.c +++ b/hw/misc/omap_clk.c @@ -XXX,XX +XXX,XX @@ void omap_clk_init(struct omap_mpu_state_s *mpu) { struct clk **i, *j, *k; int count; - int flag; - - if (cpu_is_omap310(mpu)) - flag = CLOCK_IN_OMAP310; - else if (cpu_is_omap1510(mpu)) - flag = CLOCK_IN_OMAP1510; - else - return; + int flag = CLOCK_IN_OMAP310; for (i = onchip_clks, count = 0; *i; i ++) if ((*i)->flags & flag) 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 @@ void omap_mmc_set_clk(DeviceState *dev, omap_clk clk); /* omap_i2c.c */ I2CBus *omap_i2c_bus(DeviceState *omap_i2c); -#define cpu_is_omap310(cpu) (cpu->mpu_model == omap310) -#define cpu_is_omap1510(cpu) (cpu->mpu_model == omap1510) -#define cpu_is_omap1610(cpu) (cpu->mpu_model == omap1610) -#define cpu_is_omap1710(cpu) (cpu->mpu_model == omap1710) - -#define cpu_is_omap15xx(cpu) \ - (cpu_is_omap310(cpu) || cpu_is_omap1510(cpu)) -#define cpu_is_omap16xx(cpu) \ - (cpu_is_omap1610(cpu) || cpu_is_omap1710(cpu)) - struct omap_mpu_state_s { - enum omap_mpu_model { - omap310, - omap1510, - omap1610, - omap1710, - } mpu_model; - ARMCPU *cpu; qemu_irq *drq; @@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s { MemoryRegion id_iomem; MemoryRegion id_iomem_e18; MemoryRegion id_iomem_ed4; - MemoryRegion id_iomem_e20; MemoryRegion mpui_iomem; MemoryRegion tcmi_iomem; MemoryRegion clkm_iomem; -- 2.43.0
The omap1.c file includes some functions which used to be used by the other OMAP SoC variants which we removed a while ago, but which we missed when doing that removal. They have no callers, so we can delete them. This code was the last user of hw_error() in this file, so we can also remove the hw-error.h include. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260512203414.3633237-3-peter.maydell@linaro.org --- hw/arm/omap1.c | 26 -------------------------- include/hw/arm/omap.h | 3 --- 2 files changed, 29 deletions(-) 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 "target/arm/cpu.h" #include "system/address-spaces.h" #include "exec/cpu-common.h" -#include "hw/core/hw-error.h" #include "hw/core/irq.h" #include "hw/core/qdev-properties.h" #include "hw/arm/boot.h" @@ -XXX,XX +XXX,XX @@ static struct omap_mpuio_s *omap_mpuio_init(MemoryRegion *memory, return s; } -qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s) -{ - return s->in; -} - -void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler) -{ - if (line >= 16 || line < 0) - hw_error("%s: No GPIO line %i\n", __func__, line); - s->handler[line] = handler; -} - -void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down) -{ - if (row >= 5 || row < 0) - hw_error("%s: No key %i-%i\n", __func__, col, row); - - if (down) - s->buttons[row] |= 1 << col; - else - s->buttons[row] &= ~(1 << col); - - omap_mpuio_kbd_update(s); -} - /* MicroWire Interface */ struct omap_uwire_s { MemoryRegion iomem; 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_uart_s *omap_uart_init(hwaddr base, void omap_uart_reset(struct omap_uart_s *s); struct omap_mpuio_s; -qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s); -void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler); -void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down); struct omap_uwire_s; -- 2.43.0
When we removed the support for most of the OMAP SoCs, we missed deleting a function prototype that was for a function defined in removed code. Delete it now. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260512203414.3633237-4-peter.maydell@linaro.org --- include/hw/arm/omap.h | 4 ---- 1 file changed, 4 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 soc_dma_s *omap_dma_init(hwaddr base, qemu_irq *irqs, MemoryRegion *sysmem, qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk, enum omap_dma_model model); -struct soc_dma_s *omap_dma4_init(hwaddr base, qemu_irq *irqs, - MemoryRegion *sysmem, - struct omap_mpu_state_s *mpu, int fifo, - int chans, omap_clk iclk, omap_clk fclk); void omap_dma_reset(struct soc_dma_s *s); struct dma_irq_map { -- 2.43.0
For the one remaining OMAP board, we use only the first 6 entries in the omap1_dma_irq_map[] array; the rest were for OMAP1610. Delete the now-unused elements. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260512203414.3633237-5-peter.maydell@linaro.org --- hw/arm/omap1.c | 10 ---------- 1 file changed, 10 deletions(-) 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 @@ static const struct dma_irq_map omap1_dma_irq_map[] = { { 0, OMAP_INT_DMA_CH3 }, { 0, OMAP_INT_DMA_CH4 }, { 0, OMAP_INT_DMA_CH5 }, - { 1, OMAP_INT_1610_DMA_CH6 }, - { 1, OMAP_INT_1610_DMA_CH7 }, - { 1, OMAP_INT_1610_DMA_CH8 }, - { 1, OMAP_INT_1610_DMA_CH9 }, - { 1, OMAP_INT_1610_DMA_CH10 }, - { 1, OMAP_INT_1610_DMA_CH11 }, - { 1, OMAP_INT_1610_DMA_CH12 }, - { 1, OMAP_INT_1610_DMA_CH13 }, - { 1, OMAP_INT_1610_DMA_CH14 }, - { 1, OMAP_INT_1610_DMA_CH15 } }; /* DMA ports for OMAP1 */ -- 2.43.0
Delete some #defines which we no longer use because they are for OMAP SoCs which we dropped support for. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260512203414.3633237-6-peter.maydell@linaro.org --- include/hw/arm/omap.h | 185 ------------------------------------------ 1 file changed, 185 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 @@ #define OMAP_LOCALBUS_BASE 0x30000000 #define OMAP_MPUI_BASE 0xe1000000 -#define OMAP730_SRAM_SIZE 0x00032000 #define OMAP15XX_SRAM_SIZE 0x00030000 -#define OMAP16XX_SRAM_SIZE 0x00004000 -#define OMAP1611_SRAM_SIZE 0x0003e800 #define OMAP_CS0_SIZE 0x04000000 #define OMAP_CS1_SIZE 0x04000000 #define OMAP_CS2_SIZE 0x04000000 @@ -XXX,XX +XXX,XX @@ void omap_gpio_set_clk(Omap1GpioState *gpio, omap_clk clk); * Common OMAP-15xx IRQ numbers for level 1 interrupt handler */ #define OMAP_INT_15XX_IH2_IRQ 0 -#define OMAP_INT_15XX_LB_MMU 17 -#define OMAP_INT_15XX_LOCAL_BUS 29 - -/* - * OMAP-1510 specific IRQ numbers for level 1 interrupt handler - */ -#define OMAP_INT_1510_SPI_TX 4 -#define OMAP_INT_1510_SPI_RX 5 -#define OMAP_INT_1510_DSP_MAILBOX1 10 -#define OMAP_INT_1510_DSP_MAILBOX2 11 /* * OMAP-310 specific IRQ numbers for level 1 interrupt handler @@ -XXX,XX +XXX,XX @@ void omap_gpio_set_clk(Omap1GpioState *gpio, omap_clk clk); #define OMAP_INT_310_HSB_MAILBOX1 12 #define OMAP_INT_310_HSAB_MMU 18 -/* - * OMAP-1610 specific IRQ numbers for level 1 interrupt handler - */ -#define OMAP_INT_1610_IH2_IRQ 0 -#define OMAP_INT_1610_IH2_FIQ 2 -#define OMAP_INT_1610_McBSP2_TX 4 -#define OMAP_INT_1610_McBSP2_RX 5 -#define OMAP_INT_1610_DSP_MAILBOX1 10 -#define OMAP_INT_1610_DSP_MAILBOX2 11 -#define OMAP_INT_1610_LCD_LINE 12 -#define OMAP_INT_1610_GPTIMER1 17 -#define OMAP_INT_1610_GPTIMER2 18 -#define OMAP_INT_1610_SSR_FIFO_0 29 - -/* - * OMAP-730 specific IRQ numbers for level 1 interrupt handler - */ -#define OMAP_INT_730_IH2_FIQ 0 -#define OMAP_INT_730_IH2_IRQ 1 -#define OMAP_INT_730_USB_NON_ISO 2 -#define OMAP_INT_730_USB_ISO 3 -#define OMAP_INT_730_ICR 4 -#define OMAP_INT_730_EAC 5 -#define OMAP_INT_730_GPIO_BANK1 6 -#define OMAP_INT_730_GPIO_BANK2 7 -#define OMAP_INT_730_GPIO_BANK3 8 -#define OMAP_INT_730_McBSP2TX 10 -#define OMAP_INT_730_McBSP2RX 11 -#define OMAP_INT_730_McBSP2RX_OVF 12 -#define OMAP_INT_730_LCD_LINE 14 -#define OMAP_INT_730_GSM_PROTECT 15 -#define OMAP_INT_730_TIMER3 16 -#define OMAP_INT_730_GPIO_BANK5 17 -#define OMAP_INT_730_GPIO_BANK6 18 -#define OMAP_INT_730_SPGIO_WR 29 - /* * Common IRQ numbers for level 2 interrupt handler */ @@ -XXX,XX +XXX,XX @@ void omap_gpio_set_clk(Omap1GpioState *gpio, omap_clk clk); #define OMAP_INT_RTC_ALARM 26 #define OMAP_INT_DSP_MMU 28 -/* - * OMAP-1510 specific IRQ numbers for level 2 interrupt handler - */ -#define OMAP_INT_1510_BT_MCSI1TX 16 -#define OMAP_INT_1510_BT_MCSI1RX 17 -#define OMAP_INT_1510_SoSSI_MATCH 19 -#define OMAP_INT_1510_MEM_STICK 27 -#define OMAP_INT_1510_COM_SPI_RO 31 - /* * OMAP-310 specific IRQ numbers for level 2 interrupt handler */ @@ -XXX,XX +XXX,XX @@ void omap_gpio_set_clk(Omap1GpioState *gpio, omap_clk clk); #define OMAP_INT_310_USB_W2FC_NON_ISO 30 #define OMAP_INT_310_McBSP2RX_OF 31 -/* - * OMAP-1610 specific IRQ numbers for level 2 interrupt handler - */ -#define OMAP_INT_1610_FAC 0 -#define OMAP_INT_1610_USB_HHC_2 7 -#define OMAP_INT_1610_USB_OTG 8 -#define OMAP_INT_1610_SoSSI 9 -#define OMAP_INT_1610_BT_MCSI1TX 16 -#define OMAP_INT_1610_BT_MCSI1RX 17 -#define OMAP_INT_1610_SoSSI_MATCH 19 -#define OMAP_INT_1610_MEM_STICK 27 -#define OMAP_INT_1610_McBSP2RX_OF 31 -#define OMAP_INT_1610_STI 32 -#define OMAP_INT_1610_STI_WAKEUP 33 -#define OMAP_INT_1610_GPTIMER3 34 -#define OMAP_INT_1610_GPTIMER4 35 -#define OMAP_INT_1610_GPTIMER5 36 -#define OMAP_INT_1610_GPTIMER6 37 -#define OMAP_INT_1610_GPTIMER7 38 -#define OMAP_INT_1610_GPTIMER8 39 -#define OMAP_INT_1610_GPIO_BANK2 40 -#define OMAP_INT_1610_GPIO_BANK3 41 -#define OMAP_INT_1610_MMC2 42 -#define OMAP_INT_1610_CF 43 -#define OMAP_INT_1610_WAKE_UP_REQ 46 -#define OMAP_INT_1610_GPIO_BANK4 48 -#define OMAP_INT_1610_SPI 49 -#define OMAP_INT_1610_DMA_CH6 53 -#define OMAP_INT_1610_DMA_CH7 54 -#define OMAP_INT_1610_DMA_CH8 55 -#define OMAP_INT_1610_DMA_CH9 56 -#define OMAP_INT_1610_DMA_CH10 57 -#define OMAP_INT_1610_DMA_CH11 58 -#define OMAP_INT_1610_DMA_CH12 59 -#define OMAP_INT_1610_DMA_CH13 60 -#define OMAP_INT_1610_DMA_CH14 61 -#define OMAP_INT_1610_DMA_CH15 62 -#define OMAP_INT_1610_NAND 63 - -/* - * OMAP-730 specific IRQ numbers for level 2 interrupt handler - */ -#define OMAP_INT_730_HW_ERRORS 0 -#define OMAP_INT_730_NFIQ_PWR_FAIL 1 -#define OMAP_INT_730_CFCD 2 -#define OMAP_INT_730_CFIREQ 3 -#define OMAP_INT_730_I2C 4 -#define OMAP_INT_730_PCC 5 -#define OMAP_INT_730_MPU_EXT_NIRQ 6 -#define OMAP_INT_730_SPI_100K_1 7 -#define OMAP_INT_730_SYREN_SPI 8 -#define OMAP_INT_730_VLYNQ 9 -#define OMAP_INT_730_GPIO_BANK4 10 -#define OMAP_INT_730_McBSP1TX 11 -#define OMAP_INT_730_McBSP1RX 12 -#define OMAP_INT_730_McBSP1RX_OF 13 -#define OMAP_INT_730_UART_MODEM_IRDA_2 14 -#define OMAP_INT_730_UART_MODEM_1 15 -#define OMAP_INT_730_MCSI 16 -#define OMAP_INT_730_uWireTX 17 -#define OMAP_INT_730_uWireRX 18 -#define OMAP_INT_730_SMC_CD 19 -#define OMAP_INT_730_SMC_IREQ 20 -#define OMAP_INT_730_HDQ_1WIRE 21 -#define OMAP_INT_730_TIMER32K 22 -#define OMAP_INT_730_MMC_SDIO 23 -#define OMAP_INT_730_UPLD 24 -#define OMAP_INT_730_USB_HHC_1 27 -#define OMAP_INT_730_USB_HHC_2 28 -#define OMAP_INT_730_USB_GENI 29 -#define OMAP_INT_730_USB_OTG 30 -#define OMAP_INT_730_CAMERA_IF 31 -#define OMAP_INT_730_RNG 32 -#define OMAP_INT_730_DUAL_MODE_TIMER 33 -#define OMAP_INT_730_DBB_RF_EN 34 -#define OMAP_INT_730_MPUIO_KEYPAD 35 -#define OMAP_INT_730_SHA1_MD5 36 -#define OMAP_INT_730_SPI_100K_2 37 -#define OMAP_INT_730_RNG_IDLE 38 -#define OMAP_INT_730_MPUIO 39 -#define OMAP_INT_730_LLPC_LCD_CTRL_OFF 40 -#define OMAP_INT_730_LLPC_OE_FALLING 41 -#define OMAP_INT_730_LLPC_OE_RISING 42 -#define OMAP_INT_730_LLPC_VSYNC 43 -#define OMAP_INT_730_WAKE_UP_REQ 46 -#define OMAP_INT_730_DMA_CH6 53 -#define OMAP_INT_730_DMA_CH7 54 -#define OMAP_INT_730_DMA_CH8 55 -#define OMAP_INT_730_DMA_CH9 56 -#define OMAP_INT_730_DMA_CH10 57 -#define OMAP_INT_730_DMA_CH11 58 -#define OMAP_INT_730_DMA_CH12 59 -#define OMAP_INT_730_DMA_CH13 60 -#define OMAP_INT_730_DMA_CH14 61 -#define OMAP_INT_730_DMA_CH15 62 -#define OMAP_INT_730_NAND 63 - /* omap_dma.c */ enum omap_dma_model { omap_dma_3_0, @@ -XXX,XX +XXX,XX @@ struct omap_dma_lcd_channel_s { #define OMAP_DMA_CAMERA_IF_RX 20 #define OMAP_DMA_MMC_TX 21 #define OMAP_DMA_MMC_RX 22 -#define OMAP_DMA_NAND 23 /* Not in OMAP310 */ -#define OMAP_DMA_IRQ_LCD_LINE 24 /* Not in OMAP310 */ -#define OMAP_DMA_MEMORY_STICK 25 /* Not in OMAP310 */ #define OMAP_DMA_USB_W2FC_RX0 26 #define OMAP_DMA_USB_W2FC_RX1 27 #define OMAP_DMA_USB_W2FC_RX2 28 @@ -XXX,XX +XXX,XX @@ struct omap_dma_lcd_channel_s { #define OMAP_DMA_USB_W2FC_TX1 30 #define OMAP_DMA_USB_W2FC_TX2 31 -/* These are only for 1610 */ -#define OMAP_DMA_CRYPTO_DES_IN 32 -#define OMAP_DMA_SPI_TX 33 -#define OMAP_DMA_SPI_RX 34 -#define OMAP_DMA_CRYPTO_HASH 35 -#define OMAP_DMA_CCP_ATTN 36 -#define OMAP_DMA_CCP_FIFO_NOT_EMPTY 37 -#define OMAP_DMA_CMT_APE_TX_CHAN_0 38 -#define OMAP_DMA_CMT_APE_RV_CHAN_0 39 -#define OMAP_DMA_CMT_APE_TX_CHAN_1 40 -#define OMAP_DMA_CMT_APE_RV_CHAN_1 41 -#define OMAP_DMA_CMT_APE_TX_CHAN_2 42 -#define OMAP_DMA_CMT_APE_RV_CHAN_2 43 -#define OMAP_DMA_CMT_APE_TX_CHAN_3 44 -#define OMAP_DMA_CMT_APE_RV_CHAN_3 45 -#define OMAP_DMA_CMT_APE_TX_CHAN_4 46 -#define OMAP_DMA_CMT_APE_RV_CHAN_4 47 -#define OMAP_DMA_CMT_APE_TX_CHAN_5 48 -#define OMAP_DMA_CMT_APE_RV_CHAN_5 49 -#define OMAP_DMA_CMT_APE_TX_CHAN_6 50 -#define OMAP_DMA_CMT_APE_RV_CHAN_6 51 -#define OMAP_DMA_CMT_APE_TX_CHAN_7 52 -#define OMAP_DMA_CMT_APE_RV_CHAN_7 53 -#define OMAP_DMA_MMC2_TX 54 -#define OMAP_DMA_MMC2_RX 55 -#define OMAP_DMA_CRYPTO_DES_OUT 56 - struct omap_uart_s; struct omap_uart_s *omap_uart_init(hwaddr base, qemu_irq irq, omap_clk fclk, omap_clk iclk, -- 2.43.0
The OMAP code creates a qemu_irq whose set function is omap_mpu_wakeup(), and passes that irq into omap_mpuio_init(), which saves it in its omap_mpuio_s::wakeup field. However nothing ever touches that qemu_irq again, so omap_mpu_wakeup() is never called. Remove all this as dead code. This lets us remove a direct call to cpu_interrupt(cpu, CPU_INTERRUPT_EXITTB) from within board/SoC code, which is pretty ugly and might not even do the right thing these days. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260512203414.3633237-7-peter.maydell@linaro.org --- hw/arm/omap1.c | 18 ++---------------- include/hw/arm/omap.h | 2 -- 2 files changed, 2 insertions(+), 18 deletions(-) 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 @@ struct omap_mpuio_s { qemu_irq kbd_irq; qemu_irq *in; qemu_irq handler[16]; - qemu_irq wakeup; MemoryRegion iomem; uint16_t inputs; @@ -XXX,XX +XXX,XX @@ static void omap_mpuio_onoff(void *opaque, int line, int on) static struct omap_mpuio_s *omap_mpuio_init(MemoryRegion *memory, hwaddr base, - qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup, + qemu_irq kbd_int, qemu_irq gpio_int, omap_clk clk) { struct omap_mpuio_s *s = g_new0(struct omap_mpuio_s, 1); s->irq = gpio_int; s->kbd_irq = kbd_int; - s->wakeup = wakeup; s->in = qemu_allocate_irqs(omap_mpuio_set, s, 16); omap_mpuio_reset(s); @@ -XXX,XX +XXX,XX @@ static void omap_setup_dsp_mapping(MemoryRegion *system_memory, } } -void omap_mpu_wakeup(void *opaque, int irq, int req) -{ - struct omap_mpu_state_s *mpu = opaque; - CPUState *cpu = CPU(mpu->cpu); - - if (cpu->halted) { - cpu_interrupt(cpu, CPU_INTERRUPT_EXITTB); - } -} - static const struct dma_irq_map omap1_dma_irq_map[] = { { 0, OMAP_INT_DMA_CH0_6 }, { 0, OMAP_INT_DMA_CH1_7 }, @@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *dram, s->sdram_size = memory_region_size(dram); s->sram_size = OMAP15XX_SRAM_SIZE; - s->wakeup = qemu_allocate_irq(omap_mpu_wakeup, s, 0); - /* Clocks */ omap_clk_init(s); @@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *dram, s->mpuio = omap_mpuio_init(system_memory, 0xfffb5000, qdev_get_gpio_in(s->ih[1], OMAP_INT_KEYBOARD), qdev_get_gpio_in(s->ih[1], OMAP_INT_MPUIO), - s->wakeup, omap_findclk(s, "clk32-kHz")); + omap_findclk(s, "clk32-kHz")); s->gpio = qdev_new("omap-gpio"); omap_gpio_set_clk(OMAP1_GPIO(s->gpio), omap_findclk(s, "arm_gpio_ck")); 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 { struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *sdram, const char *core); -void omap_mpu_wakeup(void *opaque, int irq, int req); - #define OMAP_BAD_REG(paddr) \ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad register %#08"HWADDR_PRIx"\n", \ __func__, paddr) -- 2.43.0
The omap_dma device has support for modelling different variants of the DMA block, as enumerated by the omap_dma_model enum: 3_0, 3_1 and 3_2. However, our one remaining OMAP SoC always passes omap_dma_3_1 into the omap_dma_init() function, so the handling for 3_0 and 3_2 is never used. Remove the support for the other versions; this lets us delete entirely two large functions that were specific to 3.2 DMA to the LCD controller, and all their associated fields in the omap_dma_lcd_channel_s struct. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260512203414.3633237-8-peter.maydell@linaro.org --- hw/dma/omap_dma.c | 348 ++---------------------------------------- include/hw/arm/omap.h | 28 ---- 2 files changed, 15 insertions(+), 361 deletions(-) diff --git a/hw/dma/omap_dma.c b/hw/dma/omap_dma.c index XXXXXXX..XXXXXXX 100644 --- a/hw/dma/omap_dma.c +++ b/hw/dma/omap_dma.c @@ -XXX,XX +XXX,XX @@ struct omap_dma_s { omap_clk clk; qemu_irq irq[4]; void (*intr_update)(struct omap_dma_s *s); - enum omap_dma_model model; int omap_3_1_mapping_disabled; uint32_t gcr; @@ -XXX,XX +XXX,XX @@ static int omap_dma_ch_reg_read(struct omap_dma_s *s, break; case 0x02: /* SYS_DMA_CCR_CH0 */ - if (s->model <= omap_dma_3_1) - *value = 0 << 10; /* FIFO_FLUSH reads as 0 */ - else - *value = ch->omap_3_1_compatible_disable << 10; + *value = 0 << 10; /* FIFO_FLUSH reads as 0 */ *value |= (ch->mode[1] << 14) | (ch->mode[0] << 12) | (ch->end_prog << 11) | @@ -XXX,XX +XXX,XX @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, ch->mode[1] = (omap_dma_addressing_t) ((value & 0xc000) >> 14); ch->mode[0] = (omap_dma_addressing_t) ((value & 0x3000) >> 12); ch->end_prog = (value & 0x0800) >> 11; - if (s->model >= omap_dma_3_2) - ch->omap_3_1_compatible_disable = (value >> 10) & 0x1; ch->repeat = (value & 0x0200) >> 9; ch->auto_init = (value & 0x0100) >> 8; ch->priority = (value & 0x0040) >> 6; @@ -XXX,XX +XXX,XX @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, return 0; } -static int omap_dma_3_2_lcd_write(struct omap_dma_lcd_channel_s *s, int offset, - uint16_t value) -{ - switch (offset) { - case 0xbc0: /* DMA_LCD_CSDP */ - s->brust_f2 = (value >> 14) & 0x3; - s->pack_f2 = (value >> 13) & 0x1; - s->data_type_f2 = (1 << ((value >> 11) & 0x3)); - s->brust_f1 = (value >> 7) & 0x3; - s->pack_f1 = (value >> 6) & 0x1; - s->data_type_f1 = (1 << ((value >> 0) & 0x3)); - break; - - case 0xbc2: /* DMA_LCD_CCR */ - s->mode_f2 = (value >> 14) & 0x3; - s->mode_f1 = (value >> 12) & 0x3; - s->end_prog = (value >> 11) & 0x1; - s->omap_3_1_compatible_disable = (value >> 10) & 0x1; - s->repeat = (value >> 9) & 0x1; - s->auto_init = (value >> 8) & 0x1; - s->running = (value >> 7) & 0x1; - s->priority = (value >> 6) & 0x1; - s->bs = (value >> 4) & 0x1; - break; - - case 0xbc4: /* DMA_LCD_CTRL */ - s->dst = (value >> 8) & 0x1; - s->src = ((value >> 6) & 0x3) << 1; - s->condition = 0; - /* Assume no bus errors and thus no BUS_ERROR irq bits. */ - s->interrupts = (value >> 1) & 1; - s->dual = value & 1; - break; - - case 0xbc8: /* TOP_B1_L */ - s->src_f1_top &= 0xffff0000; - s->src_f1_top |= 0x0000ffff & value; - break; - - case 0xbca: /* TOP_B1_U */ - s->src_f1_top &= 0x0000ffff; - s->src_f1_top |= (uint32_t)value << 16; - break; - - case 0xbcc: /* BOT_B1_L */ - s->src_f1_bottom &= 0xffff0000; - s->src_f1_bottom |= 0x0000ffff & value; - break; - - case 0xbce: /* BOT_B1_U */ - s->src_f1_bottom &= 0x0000ffff; - s->src_f1_bottom |= (uint32_t) value << 16; - break; - - case 0xbd0: /* TOP_B2_L */ - s->src_f2_top &= 0xffff0000; - s->src_f2_top |= 0x0000ffff & value; - break; - - case 0xbd2: /* TOP_B2_U */ - s->src_f2_top &= 0x0000ffff; - s->src_f2_top |= (uint32_t) value << 16; - break; - - case 0xbd4: /* BOT_B2_L */ - s->src_f2_bottom &= 0xffff0000; - s->src_f2_bottom |= 0x0000ffff & value; - break; - - case 0xbd6: /* BOT_B2_U */ - s->src_f2_bottom &= 0x0000ffff; - s->src_f2_bottom |= (uint32_t) value << 16; - break; - - case 0xbd8: /* DMA_LCD_SRC_EI_B1 */ - s->element_index_f1 = value; - break; - - case 0xbda: /* DMA_LCD_SRC_FI_B1_L */ - s->frame_index_f1 &= 0xffff0000; - s->frame_index_f1 |= 0x0000ffff & value; - break; - - case 0xbf4: /* DMA_LCD_SRC_FI_B1_U */ - s->frame_index_f1 &= 0x0000ffff; - s->frame_index_f1 |= (uint32_t) value << 16; - break; - - case 0xbdc: /* DMA_LCD_SRC_EI_B2 */ - s->element_index_f2 = value; - break; - - case 0xbde: /* DMA_LCD_SRC_FI_B2_L */ - s->frame_index_f2 &= 0xffff0000; - s->frame_index_f2 |= 0x0000ffff & value; - break; - - case 0xbf6: /* DMA_LCD_SRC_FI_B2_U */ - s->frame_index_f2 &= 0x0000ffff; - s->frame_index_f2 |= (uint32_t) value << 16; - break; - - case 0xbe0: /* DMA_LCD_SRC_EN_B1 */ - s->elements_f1 = value; - break; - - case 0xbe4: /* DMA_LCD_SRC_FN_B1 */ - s->frames_f1 = value; - break; - - case 0xbe2: /* DMA_LCD_SRC_EN_B2 */ - s->elements_f2 = value; - break; - - case 0xbe6: /* DMA_LCD_SRC_FN_B2 */ - s->frames_f2 = value; - break; - - case 0xbea: /* DMA_LCD_LCH_CTRL */ - s->lch_type = value & 0xf; - break; - - default: - return 1; - } - return 0; -} - -static int omap_dma_3_2_lcd_read(struct omap_dma_lcd_channel_s *s, int offset, - uint16_t *ret) -{ - switch (offset) { - case 0xbc0: /* DMA_LCD_CSDP */ - *ret = (s->brust_f2 << 14) | - (s->pack_f2 << 13) | - ((s->data_type_f2 >> 1) << 11) | - (s->brust_f1 << 7) | - (s->pack_f1 << 6) | - ((s->data_type_f1 >> 1) << 0); - break; - - case 0xbc2: /* DMA_LCD_CCR */ - *ret = (s->mode_f2 << 14) | - (s->mode_f1 << 12) | - (s->end_prog << 11) | - (s->omap_3_1_compatible_disable << 10) | - (s->repeat << 9) | - (s->auto_init << 8) | - (s->running << 7) | - (s->priority << 6) | - (s->bs << 4); - break; - - case 0xbc4: /* DMA_LCD_CTRL */ - qemu_irq_lower(s->irq); - *ret = (s->dst << 8) | - ((s->src & 0x6) << 5) | - (s->condition << 3) | - (s->interrupts << 1) | - s->dual; - break; - - case 0xbc8: /* TOP_B1_L */ - *ret = s->src_f1_top & 0xffff; - break; - - case 0xbca: /* TOP_B1_U */ - *ret = s->src_f1_top >> 16; - break; - - case 0xbcc: /* BOT_B1_L */ - *ret = s->src_f1_bottom & 0xffff; - break; - - case 0xbce: /* BOT_B1_U */ - *ret = s->src_f1_bottom >> 16; - break; - - case 0xbd0: /* TOP_B2_L */ - *ret = s->src_f2_top & 0xffff; - break; - - case 0xbd2: /* TOP_B2_U */ - *ret = s->src_f2_top >> 16; - break; - - case 0xbd4: /* BOT_B2_L */ - *ret = s->src_f2_bottom & 0xffff; - break; - - case 0xbd6: /* BOT_B2_U */ - *ret = s->src_f2_bottom >> 16; - break; - - case 0xbd8: /* DMA_LCD_SRC_EI_B1 */ - *ret = s->element_index_f1; - break; - - case 0xbda: /* DMA_LCD_SRC_FI_B1_L */ - *ret = s->frame_index_f1 & 0xffff; - break; - - case 0xbf4: /* DMA_LCD_SRC_FI_B1_U */ - *ret = s->frame_index_f1 >> 16; - break; - - case 0xbdc: /* DMA_LCD_SRC_EI_B2 */ - *ret = s->element_index_f2; - break; - - case 0xbde: /* DMA_LCD_SRC_FI_B2_L */ - *ret = s->frame_index_f2 & 0xffff; - break; - - case 0xbf6: /* DMA_LCD_SRC_FI_B2_U */ - *ret = s->frame_index_f2 >> 16; - break; - - case 0xbe0: /* DMA_LCD_SRC_EN_B1 */ - *ret = s->elements_f1; - break; - - case 0xbe4: /* DMA_LCD_SRC_FN_B1 */ - *ret = s->frames_f1; - break; - - case 0xbe2: /* DMA_LCD_SRC_EN_B2 */ - *ret = s->elements_f2; - break; - - case 0xbe6: /* DMA_LCD_SRC_FN_B2 */ - *ret = s->frames_f2; - break; - - case 0xbea: /* DMA_LCD_LCH_CTRL */ - *ret = s->lch_type; - break; - - default: - return 1; - } - return 0; -} - static int omap_dma_3_1_lcd_write(struct omap_dma_lcd_channel_s *s, int offset, uint16_t value) { @@ -XXX,XX +XXX,XX @@ static uint64_t omap_dma_read(void *opaque, hwaddr addr, unsigned size) switch (addr) { case 0x300 ... 0x3fe: - if (s->model <= omap_dma_3_1 || !s->omap_3_1_mapping_disabled) { - if (omap_dma_3_1_lcd_read(&s->lcd_ch, addr, &ret)) - break; - return ret; + if (omap_dma_3_1_lcd_read(&s->lcd_ch, addr, &ret)) { + break; } - /* Fall through. */ + return ret; case 0x000 ... 0x2fe: reg = addr & 0x3f; ch = (addr >> 6) & 0x0f; @@ -XXX,XX +XXX,XX @@ static uint64_t omap_dma_read(void *opaque, hwaddr addr, unsigned size) return ret; case 0x404 ... 0x4fe: - if (s->model <= omap_dma_3_1) - break; - /* Fall through. */ + break; case 0x400: if (omap_dma_sys_read(s, addr, &ret)) break; return ret; case 0xb00 ... 0xbfe: - if (s->model == omap_dma_3_2 && s->omap_3_1_mapping_disabled) { - if (omap_dma_3_2_lcd_read(&s->lcd_ch, addr, &ret)) - break; - return ret; - } break; } @@ -XXX,XX +XXX,XX @@ static void omap_dma_write(void *opaque, hwaddr addr, switch (addr) { case 0x300 ... 0x3fe: - if (s->model <= omap_dma_3_1 || !s->omap_3_1_mapping_disabled) { - if (omap_dma_3_1_lcd_write(&s->lcd_ch, addr, value)) - break; - return; + if (omap_dma_3_1_lcd_write(&s->lcd_ch, addr, value)) { + break; } - /* Fall through. */ + return; case 0x000 ... 0x2fe: reg = addr & 0x3f; ch = (addr >> 6) & 0x0f; @@ -XXX,XX +XXX,XX @@ static void omap_dma_write(void *opaque, hwaddr addr, return; case 0x404 ... 0x4fe: - if (s->model <= omap_dma_3_1) - break; - /* fall through */ + break; case 0x400: if (omap_dma_sys_write(s, addr, value)) break; return; case 0xb00 ... 0xbfe: - if (s->model == omap_dma_3_2 && s->omap_3_1_mapping_disabled) { - if (omap_dma_3_2_lcd_write(&s->lcd_ch, addr, value)) - break; - return; - } break; } @@ -XXX,XX +XXX,XX @@ static void omap_dma_clk_update(void *opaque, int line, int on) soc_dma_set_request(s->ch[i].dma, on); } -static void omap_dma_setcaps(struct omap_dma_s *s) -{ - switch (s->model) { - default: - case omap_dma_3_1: - break; - case omap_dma_3_2: - /* XXX Only available for sDMA */ - s->caps[0] = - (1 << 19) | /* Constant Fill Capability */ - (1 << 18); /* Transparent BLT Capability */ - s->caps[1] = - (1 << 1); /* 1-bit palettized capability (DMA 3.2 only) */ - s->caps[2] = - (1 << 8) | /* SEPARATE_SRC_AND_DST_INDEX_CPBLTY */ - (1 << 7) | /* DST_DOUBLE_INDEX_ADRS_CPBLTY */ - (1 << 6) | /* DST_SINGLE_INDEX_ADRS_CPBLTY */ - (1 << 5) | /* DST_POST_INCRMNT_ADRS_CPBLTY */ - (1 << 4) | /* DST_CONST_ADRS_CPBLTY */ - (1 << 3) | /* SRC_DOUBLE_INDEX_ADRS_CPBLTY */ - (1 << 2) | /* SRC_SINGLE_INDEX_ADRS_CPBLTY */ - (1 << 1) | /* SRC_POST_INCRMNT_ADRS_CPBLTY */ - (1 << 0); /* SRC_CONST_ADRS_CPBLTY */ - s->caps[3] = - (1 << 6) | /* BLOCK_SYNCHR_CPBLTY (DMA 4 only) */ - (1 << 7) | /* PKT_SYNCHR_CPBLTY (DMA 4 only) */ - (1 << 5) | /* CHANNEL_CHAINING_CPBLTY */ - (1 << 4) | /* LCh_INTERLEAVE_CPBLTY */ - (1 << 3) | /* AUTOINIT_REPEAT_CPBLTY (DMA 3.2 only) */ - (1 << 2) | /* AUTOINIT_ENDPROG_CPBLTY (DMA 3.2 only) */ - (1 << 1) | /* FRAME_SYNCHR_CPBLTY */ - (1 << 0); /* ELMNT_SYNCHR_CPBLTY */ - s->caps[4] = - (1 << 7) | /* PKT_INTERRUPT_CPBLTY (DMA 4 only) */ - (1 << 6) | /* SYNC_STATUS_CPBLTY */ - (1 << 5) | /* BLOCK_INTERRUPT_CPBLTY */ - (1 << 4) | /* LAST_FRAME_INTERRUPT_CPBLTY */ - (1 << 3) | /* FRAME_INTERRUPT_CPBLTY */ - (1 << 2) | /* HALF_FRAME_INTERRUPT_CPBLTY */ - (1 << 1) | /* EVENT_DROP_INTERRUPT_CPBLTY */ - (1 << 0); /* TIMEOUT_INTERRUPT_CPBLTY (DMA 3.2 only) */ - break; - } -} - struct soc_dma_s *omap_dma_init(hwaddr base, qemu_irq *irqs, MemoryRegion *sysmem, qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk, @@ -XXX,XX +XXX,XX @@ struct soc_dma_s *omap_dma_init(hwaddr base, qemu_irq *irqs, int num_irqs, memsize, i; struct omap_dma_s *s = g_new0(struct omap_dma_s, 1); - if (model <= omap_dma_3_1) { - num_irqs = 6; - memsize = 0x800; - } else { - num_irqs = 16; - memsize = 0xc00; - } - s->model = model; + assert(model == omap_dma_3_1); + + num_irqs = 6; + memsize = 0x800; s->mpu = mpu; s->clk = clk; s->lcd_ch.irq = lcd_irq; s->lcd_ch.mpu = mpu; - s->dma = soc_dma_init((model <= omap_dma_3_1) ? 9 : 16); + s->dma = soc_dma_init(9); s->dma->freq = omap_clk_getrate(clk); s->dma->transfer_fn = omap_dma_transfer_generic; s->dma->setup_fn = omap_dma_transfer_setup; @@ -XXX,XX +XXX,XX @@ struct soc_dma_s *omap_dma_init(hwaddr base, qemu_irq *irqs, s->ch[i].sibling = &s->ch[i + 6]; s->ch[i + 6].sibling = &s->ch[i]; } - for (i = (model <= omap_dma_3_1) ? 8 : 15; i >= 0; i --) { + for (i = 8; i >= 0; i--) { s->ch[i].dma = &s->dma->ch[i]; s->dma->ch[i].opaque = &s->ch[i]; } - omap_dma_setcaps(s); omap_clk_adduser(s->clk, qemu_allocate_irq(omap_dma_clk_update, s, 0)); omap_dma_reset(s->dma); omap_dma_clk_update(s, 0, 1); 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_dma_lcd_channel_s { hwaddr src_f2_top; hwaddr src_f2_bottom; - /* Used in OMAP DMA 3.2 gigacell */ - unsigned char brust_f1; - unsigned char pack_f1; - unsigned char data_type_f1; - unsigned char brust_f2; - unsigned char pack_f2; - unsigned char data_type_f2; - unsigned char end_prog; - unsigned char repeat; - unsigned char auto_init; - unsigned char priority; - unsigned char fs; - unsigned char running; - unsigned char bs; - unsigned char omap_3_1_compatible_disable; - unsigned char dst; - unsigned char lch_type; - int16_t element_index_f1; - int16_t element_index_f2; - int32_t frame_index_f1; - int32_t frame_index_f2; - uint16_t elements_f1; - uint16_t frames_f1; - uint16_t elements_f2; - uint16_t frames_f2; - omap_dma_addressing_t mode_f1; - omap_dma_addressing_t mode_f2; - /* Destination port is fixed. */ int interrupts; int condition; -- 2.43.0
Now we have removed the DMA 3.2 support, we call omap_dma_sys_read() only for the single address offset 0x400, and similarly for omap_dma_sys_write(). The other cases in those functions are DMA 3.2-only and now dead code. Fold the 0x400 register directly into the callers, and remove the rest. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260512203414.3633237-9-peter.maydell@linaro.org --- hw/dma/omap_dma.c | 121 ++-------------------------------------------- 1 file changed, 5 insertions(+), 116 deletions(-) diff --git a/hw/dma/omap_dma.c b/hw/dma/omap_dma.c index XXXXXXX..XXXXXXX 100644 --- a/hw/dma/omap_dma.c +++ b/hw/dma/omap_dma.c @@ -XXX,XX +XXX,XX @@ static void omap_dma_interrupts_3_1_update(struct omap_dma_s *s) qemu_irq_raise(ch[5].irq); } -static void omap_dma_interrupts_3_2_update(struct omap_dma_s *s) -{ - struct omap_dma_channel_s *ch = s->ch; - int i; - - for (i = s->chans; i; ch ++, i --) - if (ch->status) - qemu_irq_raise(ch->irq); -} - static void omap_dma_enable_3_1_mapping(struct omap_dma_s *s) { s->omap_3_1_mapping_disabled = 0; @@ -XXX,XX +XXX,XX @@ static void omap_dma_enable_3_1_mapping(struct omap_dma_s *s) s->intr_update = omap_dma_interrupts_3_1_update; } -static void omap_dma_disable_3_1_mapping(struct omap_dma_s *s) -{ - s->omap_3_1_mapping_disabled = 1; - s->chans = 16; - s->intr_update = omap_dma_interrupts_3_2_update; -} - static void omap_dma_process_request(struct omap_dma_s *s, int request) { int channel; @@ -XXX,XX +XXX,XX @@ static int omap_dma_3_1_lcd_read(struct omap_dma_lcd_channel_s *s, int offset, return 0; } -static int omap_dma_sys_write(struct omap_dma_s *s, int offset, uint16_t value) -{ - switch (offset) { - case 0x400: /* SYS_DMA_GCR */ - s->gcr = value; - break; - - case 0x404: /* DMA_GSCR */ - if (value & 0x8) - omap_dma_disable_3_1_mapping(s); - else - omap_dma_enable_3_1_mapping(s); - break; - - case 0x408: /* DMA_GRST */ - if (value & 0x1) - omap_dma_reset(s->dma); - break; - - default: - return 1; - } - return 0; -} - -static int omap_dma_sys_read(struct omap_dma_s *s, int offset, - uint16_t *ret) -{ - switch (offset) { - case 0x400: /* SYS_DMA_GCR */ - *ret = s->gcr; - break; - - case 0x404: /* DMA_GSCR */ - *ret = s->omap_3_1_mapping_disabled << 3; - break; - - case 0x408: /* DMA_GRST */ - *ret = 0; - break; - - case 0x442: /* DMA_HW_ID */ - case 0x444: /* DMA_PCh2_ID */ - case 0x446: /* DMA_PCh0_ID */ - case 0x448: /* DMA_PCh1_ID */ - case 0x44a: /* DMA_PChG_ID */ - case 0x44c: /* DMA_PChD_ID */ - *ret = 1; - break; - - case 0x44e: /* DMA_CAPS_0_U */ - *ret = (s->caps[0] >> 16) & 0xffff; - break; - case 0x450: /* DMA_CAPS_0_L */ - *ret = (s->caps[0] >> 0) & 0xffff; - break; - - case 0x452: /* DMA_CAPS_1_U */ - *ret = (s->caps[1] >> 16) & 0xffff; - break; - case 0x454: /* DMA_CAPS_1_L */ - *ret = (s->caps[1] >> 0) & 0xffff; - break; - - case 0x456: /* DMA_CAPS_2 */ - *ret = s->caps[2]; - break; - - case 0x458: /* DMA_CAPS_3 */ - *ret = s->caps[3]; - break; - - case 0x45a: /* DMA_CAPS_4 */ - *ret = s->caps[4]; - break; - - case 0x460: /* DMA_PCh2_SR */ - case 0x480: /* DMA_PCh0_SR */ - case 0x482: /* DMA_PCh1_SR */ - case 0x4c0: /* DMA_PChD_SR_0 */ - qemu_log_mask(LOG_UNIMP, - "%s: Physical Channel Status Registers not implemented\n", - __func__); - *ret = 0xff; - break; - - default: - return 1; - } - return 0; -} - static uint64_t omap_dma_read(void *opaque, hwaddr addr, unsigned size) { struct omap_dma_s *s = opaque; @@ -XXX,XX +XXX,XX @@ static uint64_t omap_dma_read(void *opaque, hwaddr addr, unsigned size) case 0x404 ... 0x4fe: break; - case 0x400: - if (omap_dma_sys_read(s, addr, &ret)) - break; - return ret; + case 0x400: /* SYS_DMA_GCR */ + return s->gcr; + break; case 0xb00 ... 0xbfe: break; @@ -XXX,XX +XXX,XX @@ static void omap_dma_write(void *opaque, hwaddr addr, case 0x404 ... 0x4fe: break; - case 0x400: - if (omap_dma_sys_write(s, addr, value)) - break; + case 0x400: /* SYS_DMA_GCR */ + s->gcr = value; return; case 0xb00 ... 0xbfe: -- 2.43.0
The OMAP DMA device has an omap_3_1_compatible_disable flag in its channel struct, which the 3.2 version of the DMA block used to tell whether it should behave compatibly with 3.1 or not. Now we have no 3.2 support, the omap_3_1_compatible_disable flag is set to false and can't be changed, so we can remove it, folding out all the conditions where we were testing it as always-false. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260512203414.3633237-10-peter.maydell@linaro.org --- hw/dma/omap_dma.c | 59 +++++++++++++++-------------------------------- 1 file changed, 19 insertions(+), 40 deletions(-) diff --git a/hw/dma/omap_dma.c b/hw/dma/omap_dma.c index XXXXXXX..XXXXXXX 100644 --- a/hw/dma/omap_dma.c +++ b/hw/dma/omap_dma.c @@ -XXX,XX +XXX,XX @@ struct omap_dma_channel_s { int fs; int bs; - /* compatibility */ - int omap_3_1_compatible_disable; - qemu_irq irq; struct omap_dma_channel_s *sibling; @@ -XXX,XX +XXX,XX @@ static void omap_dma_channel_load(struct omap_dma_channel_s *ch) { struct omap_dma_reg_set_s *a = &ch->active_set; int i, normal; - int omap_3_1 = !ch->omap_3_1_compatible_disable; /* * TODO: verify address ranges and alignment @@ -XXX,XX +XXX,XX @@ static void omap_dma_channel_load(struct omap_dma_channel_s *ch) break; case single_index: a->elem_delta[i] = ch->data_type + - ch->element_index[omap_3_1 ? 0 : i] - 1; + ch->element_index[0] - 1; a->frame_delta[i] = 0; break; case double_index: a->elem_delta[i] = ch->data_type + - ch->element_index[omap_3_1 ? 0 : i] - 1; - a->frame_delta[i] = ch->frame_index[omap_3_1 ? 0 : i] - - ch->element_index[omap_3_1 ? 0 : i]; + ch->element_index[0] - 1; + a->frame_delta[i] = ch->frame_index[0] - + ch->element_index[0]; break; default: break; @@ -XXX,XX +XXX,XX @@ static void omap_dma_transfer_generic(struct soc_dma_ch_s *dma) /* End of Block */ /* Disable the channel */ - if (ch->omap_3_1_compatible_disable) { + if (!ch->auto_init) omap_dma_disable_channel(s, ch); - if (ch->link_enabled) - omap_dma_enable_channel(s, - &s->ch[ch->link_next_ch]); - } else { - if (!ch->auto_init) - omap_dma_disable_channel(s, ch); - else if (ch->repeat || ch->end_prog) - omap_dma_channel_load(ch); - else { - ch->waiting_end_prog = 1; - omap_dma_deactivate_channel(s, ch); - } + else if (ch->repeat || ch->end_prog) + omap_dma_channel_load(ch); + else { + ch->waiting_end_prog = 1; + omap_dma_deactivate_channel(s, ch); } if (ch->interrupts & END_BLOCK_INTR) @@ -XXX,XX +XXX,XX @@ static void omap_dma_transfer_setup(struct soc_dma_ch_s *dma) /* End of Block */ /* Disable the channel */ - if (ch->omap_3_1_compatible_disable) { + if (!ch->auto_init) omap_dma_disable_channel(s, ch); - if (ch->link_enabled) - omap_dma_enable_channel(s, &s->ch[ch->link_next_ch]); - } else { - if (!ch->auto_init) - omap_dma_disable_channel(s, ch); - else if (ch->repeat || ch->end_prog) - omap_dma_channel_load(ch); - else { - ch->waiting_end_prog = 1; - omap_dma_deactivate_channel(s, ch); - } + else if (ch->repeat || ch->end_prog) + omap_dma_channel_load(ch); + else { + ch->waiting_end_prog = 1; + omap_dma_deactivate_channel(s, ch); } if (ch->interrupts & END_BLOCK_INTR) @@ -XXX,XX +XXX,XX @@ void omap_dma_reset(struct soc_dma_s *dma) s->ch[i].cpc = 0x0000; s->ch[i].fs = 0; s->ch[i].bs = 0; - s->ch[i].omap_3_1_compatible_disable = 0; memset(&s->ch[i].active_set, 0, sizeof(s->ch[i].active_set)); s->ch[i].priority = 0; s->ch[i].interleave_disabled = 0; @@ -XXX,XX +XXX,XX @@ static int omap_dma_ch_reg_read(struct omap_dma_s *s, case 0x06: /* SYS_DMA_CSR_CH0 */ *value = ch->status; ch->status &= SYNC; - if (!ch->omap_3_1_compatible_disable && ch->sibling) { + if (ch->sibling) { *value |= (ch->sibling->status & 0x3f) << 6; ch->sibling->status &= SYNC; } @@ -XXX,XX +XXX,XX @@ static int omap_dma_ch_reg_read(struct omap_dma_s *s, *value = ch->element_index[0]; break; - case 0x18: /* SYS_DMA_CPC_CH0 or DMA_CSAC */ - if (ch->omap_3_1_compatible_disable) - *value = ch->active_set.src & 0xffff; /* CSAC */ - else - *value = ch->cpc; + case 0x18: /* SYS_DMA_CPC_CH0 */ + *value = ch->cpc; break; case 0x1a: /* DMA_CDAC */ -- 2.43.0
Now we have no 3.2 DMA support, the omap_dma_enable_3_1_mapping() function is called at reset, and there is no longer anywhere that disables it. Remove the function and the unused omap_3_1_mapping_disabled struct field, and drop the indirection from omap_dma_interrupts_update() through the intr_update function pointer to omap_dma_interrupts_3_1_update(), instead inlining that last function into omap_dma_interrupts_update(). The only other thing omap_dma_enable_3_1_mapping() was doing was setting s->chans; since this is now never changed at runtime we can move its setting into the init function rather than reset. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260512203414.3633237-11-peter.maydell@linaro.org --- hw/dma/omap_dma.c | 52 ++++++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/hw/dma/omap_dma.c b/hw/dma/omap_dma.c index XXXXXXX..XXXXXXX 100644 --- a/hw/dma/omap_dma.c +++ b/hw/dma/omap_dma.c @@ -XXX,XX +XXX,XX @@ struct omap_dma_s { struct omap_mpu_state_s *mpu; omap_clk clk; qemu_irq irq[4]; - void (*intr_update)(struct omap_dma_s *s); - int omap_3_1_mapping_disabled; uint32_t gcr; uint32_t ocp; @@ -XXX,XX +XXX,XX @@ struct omap_dma_s { static inline void omap_dma_interrupts_update(struct omap_dma_s *s) { - s->intr_update(s); + struct omap_dma_channel_s *ch = s->ch; + + /* First three interrupts are shared between two channels each. */ + if (ch[0].status | ch[6].status) { + qemu_irq_raise(ch[0].irq); + } + if (ch[1].status | ch[7].status) { + qemu_irq_raise(ch[1].irq); + } + if (ch[2].status | ch[8].status) { + qemu_irq_raise(ch[2].irq); + } + if (ch[3].status) { + qemu_irq_raise(ch[3].irq); + } + if (ch[4].status) { + qemu_irq_raise(ch[4].irq); + } + if (ch[5].status) { + qemu_irq_raise(ch[5].irq); + } } static void omap_dma_channel_load(struct omap_dma_channel_s *ch) @@ -XXX,XX +XXX,XX @@ static void omap_dma_channel_end_prog(struct omap_dma_s *s, } } -static void omap_dma_interrupts_3_1_update(struct omap_dma_s *s) -{ - struct omap_dma_channel_s *ch = s->ch; - - /* First three interrupts are shared between two channels each. */ - if (ch[0].status | ch[6].status) - qemu_irq_raise(ch[0].irq); - if (ch[1].status | ch[7].status) - qemu_irq_raise(ch[1].irq); - if (ch[2].status | ch[8].status) - qemu_irq_raise(ch[2].irq); - if (ch[3].status) - qemu_irq_raise(ch[3].irq); - if (ch[4].status) - qemu_irq_raise(ch[4].irq); - if (ch[5].status) - qemu_irq_raise(ch[5].irq); -} - -static void omap_dma_enable_3_1_mapping(struct omap_dma_s *s) -{ - s->omap_3_1_mapping_disabled = 0; - s->chans = 9; - s->intr_update = omap_dma_interrupts_3_1_update; -} - static void omap_dma_process_request(struct omap_dma_s *s, int request) { int channel; @@ -XXX,XX +XXX,XX @@ void omap_dma_reset(struct soc_dma_s *dma) s->lcd_ch.condition = 0; s->lcd_ch.interrupts = 0; s->lcd_ch.dual = 0; - omap_dma_enable_3_1_mapping(s); for (i = 0; i < s->chans; i ++) { s->ch[i].suspend = 0; s->ch[i].prefetch = 0; @@ -XXX,XX +XXX,XX @@ struct soc_dma_s *omap_dma_init(hwaddr base, qemu_irq *irqs, s->clk = clk; s->lcd_ch.irq = lcd_irq; s->lcd_ch.mpu = mpu; + s->chans = 9; s->dma = soc_dma_init(9); s->dma->freq = omap_clk_getrate(clk); -- 2.43.0
The model argument to omap_dma_init() is always omap_dma_3_1, and all we do with it now is assert this; drop the argument and the enum. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260512203414.3633237-13-peter.maydell@linaro.org --- hw/arm/omap1.c | 2 +- hw/dma/omap_dma.c | 8 +++----- include/hw/arm/omap.h | 12 +++--------- 3 files changed, 7 insertions(+), 15 deletions(-) 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 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *dram, } s->dma = omap_dma_init(0xfffed800, dma_irqs, system_memory, qdev_get_gpio_in(s->ih[0], OMAP_INT_DMA_LCD), - s, omap_findclk(s, "dma_ck"), omap_dma_3_1); + s, omap_findclk(s, "dma_ck")); s->port[emiff ].addr_valid = omap_validate_emiff_addr; s->port[emifs ].addr_valid = omap_validate_emifs_addr; diff --git a/hw/dma/omap_dma.c b/hw/dma/omap_dma.c index XXXXXXX..XXXXXXX 100644 --- a/hw/dma/omap_dma.c +++ b/hw/dma/omap_dma.c @@ -XXX,XX +XXX,XX @@ static void omap_dma_clk_update(void *opaque, int line, int on) } struct soc_dma_s *omap_dma_init(hwaddr base, qemu_irq *irqs, - MemoryRegion *sysmem, - qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk, - enum omap_dma_model model) + MemoryRegion *sysmem, + qemu_irq lcd_irq, + struct omap_mpu_state_s *mpu, omap_clk clk) { int num_irqs, memsize, i; struct omap_dma_s *s = g_new0(struct omap_dma_s, 1); - assert(model == omap_dma_3_1); - num_irqs = 6; memsize = 0x800; s->mpu = mpu; 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 @@ void omap_gpio_set_clk(Omap1GpioState *gpio, omap_clk clk); #define OMAP_INT_310_McBSP2RX_OF 31 /* omap_dma.c */ -enum omap_dma_model { - omap_dma_3_0, - omap_dma_3_1, - omap_dma_3_2, -}; - struct soc_dma_s; struct soc_dma_s *omap_dma_init(hwaddr base, qemu_irq *irqs, - MemoryRegion *sysmem, - qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk, - enum omap_dma_model model); + MemoryRegion *sysmem, + qemu_irq lcd_irq, + struct omap_mpu_state_s *mpu, omap_clk clk); void omap_dma_reset(struct soc_dma_s *s); struct dma_irq_map { -- 2.43.0
The translate_for_debug method is supposed to return attributes that include the debug flag being set. We forgot this when implementing the method for Arm. Fixes: abefca8e7f957 ("target/arm: Implement translate_for_debug") Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260515131245.366240-1-peter.maydell@linaro.org --- target/arm/ptw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -XXX,XX +XXX,XX @@ static bool arm_cpu_get_phys_addr(CPUARMState *env, vaddr addr, /* translation succeeded */ result->physaddr = res.f.phys_addr; result->attrs = res.f.attrs; + result->attrs.debug = 1; result->lg_page_size = res.f.lg_page_size; } return fault; -- 2.43.0
We want to bring all the get_phys_addr* functions in ptw.c into line with the sense that translate_for_debug() has and which seems more logical: true on success, and false on failure. Start with get_phys_addr_disabled(). Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260515142541.571911-2-peter.maydell@linaro.org --- target/arm/ptw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_disabled(CPUARMState *env, fi->type = ARMFault_AddressSize; fi->level = 0; fi->stage2 = false; - return 1; + return false; } /* @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_disabled(CPUARMState *env, result->f.lg_page_size = TARGET_PAGE_BITS; result->cacheattrs.shareability = shareability; result->cacheattrs.attrs = memattr; - return false; + return true; } static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw, @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw, case ARMMMUIdx_Phys_Root: case ARMMMUIdx_Phys_Realm: /* Checking Phys early avoids special casing later vs regime_el. */ - return get_phys_addr_disabled(env, ptw, address, access_type, + return !get_phys_addr_disabled(env, ptw, address, access_type, result, fi); case ARMMMUIdx_Stage1_E0: @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw, /* Definitely a real MMU, not an MPU */ if (regime_translation_disabled(env, mmu_idx, ptw->in_space)) { - return get_phys_addr_disabled(env, ptw, address, access_type, + return !get_phys_addr_disabled(env, ptw, address, access_type, result, fi); } -- 2.43.0
Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260515142541.571911-3-peter.maydell@linaro.org --- target/arm/ptw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -XXX,XX +XXX,XX @@ static bool lpae_block_desc_valid(ARMCPU *cpu, bool ds, /** * get_phys_addr_lpae: perform one stage of page table walk, LPAE format * - * Returns false if the translation was successful. Otherwise, phys_ptr, + * Returns true if the translation was successful. Otherwise, phys_ptr, * attrs, prot and page_size may not be filled in, and the populated fsr * value provides information on why the translation aborted, in the format * of a long-format DFSR/IFSR fault register, with the following caveat: @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw, result->f.phys_addr = descaddr; result->f.lg_page_size = ctz64(page_size); - return false; + return true; do_translation_fault: fi->type = ARMFault_Translation; @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw, fi->stage2 = regime_is_stage2(mmu_idx); } fi->s1ns = fault_s1ns(ptw->cur_space, mmu_idx); - return true; + return false; } static bool get_phys_addr_pmsav5(CPUARMState *env, @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw, } if (regime_using_lpae_format(env, mmu_idx)) { - return get_phys_addr_lpae(env, ptw, address, access_type, + return !get_phys_addr_lpae(env, ptw, address, access_type, memop, result, fi); } else if (arm_feature(env, ARM_FEATURE_V7) || regime_sctlr(env, mmu_idx) & SCTLR_XP) { -- 2.43.0
Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260515142541.571911-4-peter.maydell@linaro.org --- target/arm/ptw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v6(CPUARMState *env, S1Translate *ptw, result->f.attrs.space = out_space; result->f.attrs.secure = arm_space_is_secure(out_space); result->f.phys_addr = phys_addr; - return false; + return true; do_fault: fi->domain = domain; fi->level = level; - return true; + return false; } /* @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw, memop, result, fi); } else if (arm_feature(env, ARM_FEATURE_V7) || regime_sctlr(env, mmu_idx) & SCTLR_XP) { - return get_phys_addr_v6(env, ptw, address, access_type, result, fi); + return !get_phys_addr_v6(env, ptw, address, access_type, result, fi); } else { return get_phys_addr_v5(env, ptw, address, access_type, result, fi); } -- 2.43.0
Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260515142541.571911-5-peter.maydell@linaro.org --- target/arm/ptw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v5(CPUARMState *env, S1Translate *ptw, goto do_fault; } result->f.phys_addr = phys_addr; - return false; + return true; do_fault: fi->domain = domain; fi->level = level; - return true; + return false; } static bool get_phys_addr_v6(CPUARMState *env, S1Translate *ptw, @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw, regime_sctlr(env, mmu_idx) & SCTLR_XP) { return !get_phys_addr_v6(env, ptw, address, access_type, result, fi); } else { - return get_phys_addr_v5(env, ptw, address, access_type, result, fi); + return !get_phys_addr_v5(env, ptw, address, access_type, result, fi); } } -- 2.43.0
Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260515142541.571911-6-peter.maydell@linaro.org --- target/arm/ptw.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav5(CPUARMState *env, /* MPU disabled. */ result->f.phys_addr = address; result->f.prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; - return false; + return true; } result->f.phys_addr = address; @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav5(CPUARMState *env, } if (n < 0) { fi->type = ARMFault_Background; - return true; + return false; } if (access_type == MMU_INST_FETCH) { @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav5(CPUARMState *env, case 0: fi->type = ARMFault_Permission; fi->level = 1; - return true; + return false; case 1: if (is_user) { fi->type = ARMFault_Permission; fi->level = 1; - return true; + return false; } result->f.prot = PAGE_READ | PAGE_WRITE; break; @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav5(CPUARMState *env, if (is_user) { fi->type = ARMFault_Permission; fi->level = 1; - return true; + return false; } result->f.prot = PAGE_READ; break; @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav5(CPUARMState *env, /* Bad permission. */ fi->type = ARMFault_Permission; fi->level = 1; - return true; + return false; } result->f.prot |= PAGE_EXEC; - return false; + return true; } static void get_phys_addr_pmsav7_default(CPUARMState *env, ARMMMUIdx mmu_idx, @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw, result, fi); } else { /* Pre-v7 MPU */ - ret = get_phys_addr_pmsav5(env, ptw, address, access_type, + ret = !get_phys_addr_pmsav5(env, ptw, address, access_type, result, fi); } qemu_log_mask(CPU_LOG_MMU, "PMSA MPU lookup for %s at 0x%08" PRIx32 -- 2.43.0
Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260515142541.571911-7-peter.maydell@linaro.org --- target/arm/ptw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav7(CPUARMState *env, if (!pmsav7_use_background_region(cpu, mmu_idx, secure, is_user)) { /* background fault */ fi->type = ARMFault_Background; - return true; + return false; } get_phys_addr_pmsav7_default(env, mmu_idx, address, &result->f.prot); @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav7(CPUARMState *env, fi->type = ARMFault_Permission; fi->level = 1; - return (ptw->in_prot_check & ~result->f.prot) != 0; + return (ptw->in_prot_check & ~result->f.prot) == 0; } static uint32_t *regime_rbar(CPUARMState *env, ARMMMUIdx mmu_idx, @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw, result, fi); } else if (arm_feature(env, ARM_FEATURE_V7)) { /* PMSAv7 */ - ret = get_phys_addr_pmsav7(env, ptw, address, access_type, + ret = !get_phys_addr_pmsav7(env, ptw, address, access_type, result, fi); } else { /* Pre-v7 MPU */ -- 2.43.0
Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260515142541.571911-8-peter.maydell@linaro.org --- target/arm/ptw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav8(CPUARMState *env, result->f.lg_page_size = sattrs.subpage ? 0 : TARGET_PAGE_BITS; result->f.phys_addr = address; result->f.prot = 0; - return true; + return false; } } else { /* @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav8(CPUARMState *env, result->f.lg_page_size = sattrs.subpage ? 0 : TARGET_PAGE_BITS; result->f.phys_addr = address; result->f.prot = 0; - return true; + return false; } } } - ret = pmsav8_mpu_lookup(env, address, access_type, ptw->in_prot_check, + ret = !pmsav8_mpu_lookup(env, address, access_type, ptw->in_prot_check, mmu_idx, secure, result, fi, NULL); /* * For two-stage PMSA translations, s2prot holds the stage 2 @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw, if (arm_feature(env, ARM_FEATURE_V8)) { /* PMSAv8 */ - ret = get_phys_addr_pmsav8(env, ptw, address, access_type, + ret = !get_phys_addr_pmsav8(env, ptw, address, access_type, result, fi); } else if (arm_feature(env, ARM_FEATURE_V7)) { /* PMSAv7 */ -- 2.43.0
Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260515142541.571911-9-peter.maydell@linaro.org --- target/arm/ptw.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, * If the region hit doesn't cover the entire TARGET_PAGE the address * is within, then we set the result page_size to 1 to force the * memory system to use a subpage. + * Return true on success, false on fault. */ ARMCPU *cpu = env_archcpu(env); bool is_user = regime_is_user(mmu_idx); @@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, if (arm_feature(env, ARM_FEATURE_M)) { fi->level = 1; } - return true; + return false; } matchregion = n; @@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, } else { fi->type = ARMFault_Permission; } - return true; + return false; } if (matchregion == -1) { @@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, if (arm_feature(env, ARM_FEATURE_M)) { fi->level = 1; } - return (prot_check & ~result->f.prot) != 0; + return (prot_check & ~result->f.prot) == 0; } static bool v8m_is_sau_exempt(CPUARMState *env, @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav8(CPUARMState *env, } } - ret = !pmsav8_mpu_lookup(env, address, access_type, ptw->in_prot_check, + ret = pmsav8_mpu_lookup(env, address, access_type, ptw->in_prot_check, mmu_idx, secure, result, fi, NULL); /* * For two-stage PMSA translations, s2prot holds the stage 2 -- 2.43.0
Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260515142541.571911-10-peter.maydell@linaro.org --- target/arm/ptw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw, /* If S1 fails, return early. */ if (ret) { - return ret; + return !ret; } ipa = result->f.phys_addr; @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw, /* If S2 fails, return early. */ if (ret) { - return ret; + return !ret; } /* @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw, result->f.attrs.space = arm_secure_to_space(result->f.attrs.secure); } - return false; + return true; } static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw, @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw, ptw->in_mmu_idx = mmu_idx = s1_mmu_idx; if (arm_feature(env, ARM_FEATURE_EL2) && !regime_translation_disabled(env, ARMMMUIdx_Stage2, ptw->in_space)) { - return get_phys_addr_twostage(env, ptw, address, access_type, + return !get_phys_addr_twostage(env, ptw, address, access_type, memop, result, fi); } /* fall through */ -- 2.43.0
Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260515142541.571911-11-peter.maydell@linaro.org --- target/arm/ptw.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw, memop, result, fi); /* If S1 fails, return early. */ - if (ret) { - return !ret; + if (!ret) { + return ret; } ipa = result->f.phys_addr; @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw, result->f.prot = s1_prot & result->s2prot; /* If S2 fails, return early. */ - if (ret) { - return !ret; + if (!ret) { + return ret; } /* @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw, case ARMMMUIdx_Phys_Root: case ARMMMUIdx_Phys_Realm: /* Checking Phys early avoids special casing later vs regime_el. */ - return !get_phys_addr_disabled(env, ptw, address, access_type, + return get_phys_addr_disabled(env, ptw, address, access_type, result, fi); case ARMMMUIdx_Stage1_E0: @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw, ptw->in_mmu_idx = mmu_idx = s1_mmu_idx; if (arm_feature(env, ARM_FEATURE_EL2) && !regime_translation_disabled(env, ARMMMUIdx_Stage2, ptw->in_space)) { - return !get_phys_addr_twostage(env, ptw, address, access_type, + return get_phys_addr_twostage(env, ptw, address, access_type, memop, result, fi); } /* fall through */ @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw, if (arm_feature(env, ARM_FEATURE_V8)) { /* PMSAv8 */ - ret = !get_phys_addr_pmsav8(env, ptw, address, access_type, + ret = get_phys_addr_pmsav8(env, ptw, address, access_type, result, fi); } else if (arm_feature(env, ARM_FEATURE_V7)) { /* PMSAv7 */ - ret = !get_phys_addr_pmsav7(env, ptw, address, access_type, + ret = get_phys_addr_pmsav7(env, ptw, address, access_type, result, fi); } else { /* Pre-v7 MPU */ - ret = !get_phys_addr_pmsav5(env, ptw, address, access_type, + ret = get_phys_addr_pmsav5(env, ptw, address, access_type, result, fi); } qemu_log_mask(CPU_LOG_MMU, "PMSA MPU lookup for %s at 0x%08" PRIx32 @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw, access_type == MMU_DATA_LOAD ? "reading" : (access_type == MMU_DATA_STORE ? "writing" : "execute"), (uint32_t)address, mmu_idx, - ret ? "Miss" : "Hit", + ret ? "Hit" : "Miss", result->f.prot & PAGE_READ ? 'r' : '-', result->f.prot & PAGE_WRITE ? 'w' : '-', result->f.prot & PAGE_EXEC ? 'x' : '-'); @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw, /* Definitely a real MMU, not an MPU */ if (regime_translation_disabled(env, mmu_idx, ptw->in_space)) { - return !get_phys_addr_disabled(env, ptw, address, access_type, + return get_phys_addr_disabled(env, ptw, address, access_type, result, fi); } if (regime_using_lpae_format(env, mmu_idx)) { - return !get_phys_addr_lpae(env, ptw, address, access_type, + return get_phys_addr_lpae(env, ptw, address, access_type, memop, result, fi); } else if (arm_feature(env, ARM_FEATURE_V7) || regime_sctlr(env, mmu_idx) & SCTLR_XP) { - return !get_phys_addr_v6(env, ptw, address, access_type, result, fi); + return get_phys_addr_v6(env, ptw, address, access_type, result, fi); } else { - return !get_phys_addr_v5(env, ptw, address, access_type, result, fi); + return get_phys_addr_v5(env, ptw, address, access_type, result, fi); } } @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_gpc(CPUARMState *env, S1Translate *ptw, GetPhysAddrResult *result, ARMMMUFaultInfo *fi) { - if (get_phys_addr_nogpc(env, ptw, address, access_type, + if (!get_phys_addr_nogpc(env, ptw, address, access_type, memop, result, fi)) { return true; } @@ -XXX,XX +XXX,XX @@ bool get_phys_addr_for_at(CPUARMState *env, vaddr address, * check is handled or bypassed by .in_prot_check) and "memop = MO_8" * bypasses any alignment check. */ - return get_phys_addr_nogpc(env, &ptw, address, + return !get_phys_addr_nogpc(env, &ptw, address, MMU_DATA_LOAD, MO_8, result, fi); } -- 2.43.0
Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260515142541.571911-12-peter.maydell@linaro.org --- target/arm/ptw.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw, }; GetPhysAddrResult s2 = { }; - if (get_phys_addr_gpc(env, &s2ptw, addr, MMU_DATA_LOAD, 0, &s2, fi)) { + if (!get_phys_addr_gpc(env, &s2ptw, addr, MMU_DATA_LOAD, 0, &s2, fi)) { goto fail; } @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_gpc(CPUARMState *env, S1Translate *ptw, { if (!get_phys_addr_nogpc(env, ptw, address, access_type, memop, result, fi)) { - return true; + return false; } if (FIELD_EX64(env->cp15.gpccr_el3, GPCCR, GPC)) { @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_gpc(CPUARMState *env, S1Translate *ptw, result->f.attrs.space, ptw->in_space, fi)) { fi->type = ARMFault_GPCFOnOutput; - return true; + return false; } } - return false; + return true; } bool get_phys_addr_for_at(CPUARMState *env, vaddr address, @@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, vaddr address, .in_prot_check = 1 << access_type, }; - return get_phys_addr_gpc(env, &ptw, address, access_type, + return !get_phys_addr_gpc(env, &ptw, address, access_type, memop, result, fi); } @@ -XXX,XX +XXX,XX @@ static bool arm_cpu_get_phys_addr(CPUARMState *env, vaddr addr, }; GetPhysAddrResult res = {}; ARMMMUFaultInfo fi = {}; - bool fault = get_phys_addr_gpc(env, &ptw, addr, MMU_DATA_LOAD, 0, &res, &fi); + bool ok = get_phys_addr_gpc(env, &ptw, addr, MMU_DATA_LOAD, 0, &res, &fi); - if (!fault) { + if (ok) { /* translation succeeded */ result->physaddr = res.f.phys_addr; result->attrs = res.f.attrs; result->attrs.debug = 1; result->lg_page_size = res.f.lg_page_size; } - return fault; + return !ok; } bool arm_cpu_translate_for_debug(CPUState *cs, vaddr addr, -- 2.43.0
Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260515142541.571911-13-peter.maydell@linaro.org --- target/arm/ptw.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -XXX,XX +XXX,XX @@ static bool arm_cpu_get_phys_addr(CPUARMState *env, vaddr addr, result->attrs.debug = 1; result->lg_page_size = res.f.lg_page_size; } - return !ok; + return ok; } bool arm_cpu_translate_for_debug(CPUState *cs, vaddr addr, @@ -XXX,XX +XXX,XX @@ bool arm_cpu_translate_for_debug(CPUState *cs, vaddr addr, CPUARMState *env = &cpu->env; ARMMMUIdx mmu_idx = arm_mmu_idx(env); - /* - * Note that this function returns true on translation success, - * but arm_cpu_get_phys_addr() and all the other get_phys_addr - * style functions in this file return true on failure. - */ - if (!arm_cpu_get_phys_addr(env, addr, result, mmu_idx)) { + if (arm_cpu_get_phys_addr(env, addr, result, mmu_idx)) { return true; } @@ -XXX,XX +XXX,XX @@ bool arm_cpu_translate_for_debug(CPUState *cs, vaddr addr, switch (mmu_idx) { case ARMMMUIdx_E10_1: case ARMMMUIdx_E10_1_PAN: - return !arm_cpu_get_phys_addr(env, addr, result, ARMMMUIdx_E10_0); + return arm_cpu_get_phys_addr(env, addr, result, ARMMMUIdx_E10_0); case ARMMMUIdx_E20_2: case ARMMMUIdx_E20_2_PAN: - return !arm_cpu_get_phys_addr(env, addr, result, ARMMMUIdx_E20_0); + return arm_cpu_get_phys_addr(env, addr, result, ARMMMUIdx_E20_0); default: /* translation failed */ return false; -- 2.43.0
Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260515142541.571911-14-peter.maydell@linaro.org --- target/arm/internals.h | 2 ++ target/arm/ptw.c | 2 +- target/arm/tcg/cpregs-at.c | 12 ++++++------ 3 files changed, 9 insertions(+), 7 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 @@ bool get_phys_addr(CPUARMState *env, vaddr address, * * Similar to get_phys_addr, but for use by AccessType_AT, i.e. * system instructions for address translation. + * + * Returns: false on translation failure, true on success. */ bool get_phys_addr_for_at(CPUARMState *env, vaddr address, unsigned prot_check, ARMMMUIdx mmu_idx, ARMSecuritySpace space, diff --git a/target/arm/ptw.c b/target/arm/ptw.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -XXX,XX +XXX,XX @@ bool get_phys_addr_for_at(CPUARMState *env, vaddr address, * check is handled or bypassed by .in_prot_check) and "memop = MO_8" * bypasses any alignment check. */ - return !get_phys_addr_nogpc(env, &ptw, address, + return get_phys_addr_nogpc(env, &ptw, address, MMU_DATA_LOAD, MO_8, result, fi); } diff --git a/target/arm/tcg/cpregs-at.c b/target/arm/tcg/cpregs-at.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/cpregs-at.c +++ b/target/arm/tcg/cpregs-at.c @@ -XXX,XX +XXX,XX @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value, bool format64 = false; ARMMMUFaultInfo fi = {}; GetPhysAddrResult res = {}; - bool ret = get_phys_addr_for_at(env, value, prot_check, - mmu_idx, ss, &res, &fi); + bool ok = get_phys_addr_for_at(env, value, prot_check, + mmu_idx, ss, &res, &fi); /* * ATS operations only do S1 or S1+S2 translations, so we never * have to deal with the ARMCacheAttrs format for S2 only. * (Note that res fields are only valid on ptw success.) */ - assert(ret || !res.cacheattrs.is_s2_format); + assert(!ok || !res.cacheattrs.is_s2_format); - if (ret) { + if (!ok) { /* * Some kinds of translation fault must cause exceptions rather * than being reported in the PAR. @@ -XXX,XX +XXX,XX @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value, if (format64) { /* Create a 64-bit PAR */ par64 = (1 << 11); /* LPAE bit always set */ - if (!ret) { + if (ok) { par64 |= res.f.phys_addr & ~0xfffULL; if (!res.f.attrs.secure) { par64 |= (1 << 9); /* NS */ @@ -XXX,XX +XXX,XX @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value, * translation table format (with WnR always clear). * Convert it to a 32-bit PAR. */ - if (!ret) { + if (ok) { /* We do not set any attribute bits in the PAR */ if (res.f.lg_page_size == 24 && arm_feature(env, ARM_FEATURE_V7)) { -- 2.43.0
This completes the conversion of this family of functions to returning true on success and false on failure. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260515142541.571911-15-peter.maydell@linaro.org --- target/arm/internals.h | 2 +- target/arm/ptw.c | 2 +- target/arm/tcg/m_helper.c | 8 ++++---- target/arm/tcg/tlb_helper.c | 6 +++--- 4 files changed, 9 insertions(+), 9 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 @@ typedef struct GetPhysAddrResult { * by doing a translation table walk on MMU based systems or using the * MPU state on MPU based systems. * - * Returns false if the translation was successful. Otherwise, phys_ptr, attrs, + * Returns true if the translation was successful. Otherwise, phys_ptr, attrs, * prot and page_size may not be filled in, and the populated fsr value provides * information on why the translation aborted, in the format of a * DFSR/IFSR fault register, with the following caveats: diff --git a/target/arm/ptw.c b/target/arm/ptw.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, vaddr address, .in_prot_check = 1 << access_type, }; - return !get_phys_addr_gpc(env, &ptw, address, access_type, + return get_phys_addr_gpc(env, &ptw, address, access_type, memop, result, fi); } diff --git a/target/arm/tcg/m_helper.c b/target/arm/tcg/m_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/m_helper.c +++ b/target/arm/tcg/m_helper.c @@ -XXX,XX +XXX,XX @@ static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value, int exc; bool exc_secure; - if (get_phys_addr(env, addr, MMU_DATA_STORE, 0, mmu_idx, &res, &fi)) { + if (!get_phys_addr(env, addr, MMU_DATA_STORE, 0, mmu_idx, &res, &fi)) { /* MPU/SAU lookup failed */ if (fi.type == ARMFault_QEMU_SFault) { if (mode == STACK_LAZYFP) { @@ -XXX,XX +XXX,XX @@ static bool v7m_stack_read(ARMCPU *cpu, uint32_t *dest, uint32_t addr, bool exc_secure; uint32_t value; - if (get_phys_addr(env, addr, MMU_DATA_LOAD, 0, mmu_idx, &res, &fi)) { + if (!get_phys_addr(env, addr, MMU_DATA_LOAD, 0, mmu_idx, &res, &fi)) { /* MPU/SAU lookup failed */ if (fi.type == ARMFault_QEMU_SFault) { qemu_log_mask(CPU_LOG_INT, @@ -XXX,XX +XXX,XX @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx, bool secure, "...really SecureFault with SFSR.INVEP\n"); return false; } - if (get_phys_addr(env, addr, MMU_INST_FETCH, 0, mmu_idx, &res, &fi)) { + if (!get_phys_addr(env, addr, MMU_INST_FETCH, 0, mmu_idx, &res, &fi)) { /* the MPU lookup failed */ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_IACCVIOL_MASK; armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM, env->v7m.secure); @@ -XXX,XX +XXX,XX @@ static bool v7m_read_sg_stack_word(ARMCPU *cpu, ARMMMUIdx mmu_idx, ARMMMUFaultInfo fi = {}; uint32_t value; - if (get_phys_addr(env, addr, MMU_DATA_LOAD, 0, mmu_idx, &res, &fi)) { + if (!get_phys_addr(env, addr, MMU_DATA_LOAD, 0, mmu_idx, &res, &fi)) { /* MPU/SAU lookup failed */ if (fi.type == ARMFault_QEMU_SFault) { qemu_log_mask(CPU_LOG_INT, diff --git a/target/arm/tcg/tlb_helper.c b/target/arm/tcg/tlb_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/tlb_helper.c +++ b/target/arm/tcg/tlb_helper.c @@ -XXX,XX +XXX,XX @@ bool arm_cpu_tlb_fill_align(CPUState *cs, CPUTLBEntryFull *out, vaddr address, fi->type = ARMFault_Alignment; } else if (address & ((1 << memop_alignment_bits(memop)) - 1)) { fi->type = ARMFault_Alignment; - } else if (!get_phys_addr(&cpu->env, address, access_type, memop, - core_to_arm_mmu_idx(&cpu->env, mmu_idx), - &res, fi)) { + } else if (get_phys_addr(&cpu->env, address, access_type, memop, + core_to_arm_mmu_idx(&cpu->env, mmu_idx), + &res, fi)) { res.f.extra.arm.pte_attrs = res.cacheattrs.attrs; res.f.extra.arm.shareability = res.cacheattrs.shareability; *out = res.f; -- 2.43.0
On a debug build, the virt_vbsa functional test takes about 2 minutes to run on my machine, so it tends to time out. Bump the timeout to 4 mins. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Thomas Huth <thuth@redhat.com> Message-id: 20260518160440.1037245-1-peter.maydell@linaro.org --- tests/functional/aarch64/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/functional/aarch64/meson.build b/tests/functional/aarch64/meson.build index XXXXXXX..XXXXXXX 100644 --- a/tests/functional/aarch64/meson.build +++ b/tests/functional/aarch64/meson.build @@ -XXX,XX +XXX,XX @@ test_aarch64_timeouts = { 'tuxrun' : 240, 'virt' : 360, 'virt_gpu' : 480, + 'virt_vbsa' : 240, } tests_aarch64_system_quick = [ -- 2.43.0
The behaviour of floating-point maximum and minimum insns has some odd special cases when FPCR.AH=1. We get this right in most places (for instance, the ASIMD FMAXP, FMINP) but forgot about it for the SVE2 versions of FMAXP and FMINP. Cc: qemu-stable@nongnu.org Fixes: 384433e70983 ("target/arm: Implement FPCR.AH semantics for FMINP and FMAXP") Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Message-id: 20260521122913.1565011-2-peter.maydell@linaro.org --- target/arm/tcg/helper-sve-defs.h | 14 ++++++++++++++ target/arm/tcg/sve_helper.c | 8 ++++++++ target/arm/tcg/translate-sve.c | 4 ++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/target/arm/tcg/helper-sve-defs.h b/target/arm/tcg/helper-sve-defs.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/helper-sve-defs.h +++ b/target/arm/tcg/helper-sve-defs.h @@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_6(sve2_fminp_zpzz_s, TCG_CALL_NO_RWG, DEF_HELPER_FLAGS_6(sve2_fminp_zpzz_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, fpst, i32) +DEF_HELPER_FLAGS_6(sve2_ah_fmaxp_zpzz_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, fpst, i32) +DEF_HELPER_FLAGS_6(sve2_ah_fmaxp_zpzz_s, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, fpst, i32) +DEF_HELPER_FLAGS_6(sve2_ah_fmaxp_zpzz_d, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, fpst, i32) + +DEF_HELPER_FLAGS_6(sve2_ah_fminp_zpzz_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, fpst, i32) +DEF_HELPER_FLAGS_6(sve2_ah_fminp_zpzz_s, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, fpst, i32) +DEF_HELPER_FLAGS_6(sve2_ah_fminp_zpzz_d, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, fpst, i32) + DEF_HELPER_FLAGS_5(sve2_eor3, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_5(sve2_bcax, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_5(sve2_bsl1n, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) diff --git a/target/arm/tcg/sve_helper.c b/target/arm/tcg/sve_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/sve_helper.c +++ b/target/arm/tcg/sve_helper.c @@ -XXX,XX +XXX,XX @@ DO_ZPZZ_PAIR_FP(sve2_fminp_zpzz_h, float16, H1_2, float16_min) DO_ZPZZ_PAIR_FP(sve2_fminp_zpzz_s, float32, H1_4, float32_min) DO_ZPZZ_PAIR_FP(sve2_fminp_zpzz_d, float64, H1_8, float64_min) +DO_ZPZZ_PAIR_FP(sve2_ah_fmaxp_zpzz_h, float16, H1_2, helper_vfp_ah_maxh) +DO_ZPZZ_PAIR_FP(sve2_ah_fmaxp_zpzz_s, float32, H1_4, helper_vfp_ah_maxs) +DO_ZPZZ_PAIR_FP(sve2_ah_fmaxp_zpzz_d, float64, H1_8, helper_vfp_ah_maxd) + +DO_ZPZZ_PAIR_FP(sve2_ah_fminp_zpzz_h, float16, H1_2, helper_vfp_ah_minh) +DO_ZPZZ_PAIR_FP(sve2_ah_fminp_zpzz_s, float32, H1_4, helper_vfp_ah_mins) +DO_ZPZZ_PAIR_FP(sve2_ah_fminp_zpzz_d, float64, H1_8, helper_vfp_ah_mind) + #undef DO_ZPZZ_PAIR_FP /* Three-operand expander, controlled by a predicate, in which the diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-sve.c +++ b/target/arm/tcg/translate-sve.c @@ -XXX,XX +XXX,XX @@ TRANS_FEAT_NONSTREAMING(HISTSEG, aa64_sve2, gen_gvec_ool_arg_zzz, DO_ZPZZ_FP(FADDP, aa64_sme_or_sve2, sve2_faddp_zpzz) DO_ZPZZ_FP(FMAXNMP, aa64_sme_or_sve2, sve2_fmaxnmp_zpzz) DO_ZPZZ_FP(FMINNMP, aa64_sme_or_sve2, sve2_fminnmp_zpzz) -DO_ZPZZ_FP(FMAXP, aa64_sme_or_sve2, sve2_fmaxp_zpzz) -DO_ZPZZ_FP(FMINP, aa64_sme_or_sve2, sve2_fminp_zpzz) +DO_ZPZZ_AH_FP(FMAXP, aa64_sme_or_sve2, sve2_fmaxp_zpzz, sve2_ah_fmaxp_zpzz) +DO_ZPZZ_AH_FP(FMINP, aa64_sme_or_sve2, sve2_fminp_zpzz, sve2_ah_fminp_zpzz) static bool do_fmmla(DisasContext *s, arg_rrrr_esz *a, gen_helper_gvec_4_ptr *fn) -- 2.43.0
We should be using the F16-specific float_status for conversions from half-precision, because halfprec inputs never set Input Denormal. If we use the FPST_A64 fpstatus then we will incorrectly set FPCR.IDC for input-denormals when FPCR.AH=1. In commit e07b48995aaa we updated most of the halfprec-to-other conversion insns to use FPST_A64_F16 as part of implementing FEAT_AHP. However we missed the SVE FCVTLT instruction, which has a halfprec-to-single encoding. Correct the FPST we use for the hs variant of FCVTLT. Cc: qemu-stable@nongnu.org Fixes: e07b48995aaa ("target/arm: Use FPST_A64_F16 for halfprec-to-other conversions")a Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260521122913.1565011-3-peter.maydell@linaro.org --- target/arm/tcg/translate-sve.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-sve.c +++ b/target/arm/tcg/translate-sve.c @@ -XXX,XX +XXX,XX @@ TRANS_FEAT(BFCVTNT, aa64_sme_sve_bf16, gen_gvec_fpst_arg_zpz, s->fpcr_ah ? FPST_AH : FPST_A64) TRANS_FEAT(FCVTLT_hs, aa64_sme_or_sve2, gen_gvec_fpst_arg_zpz, - gen_helper_sve2_fcvtlt_hs, a, 0, FPST_A64) + gen_helper_sve2_fcvtlt_hs, a, 0, FPST_A64_F16) TRANS_FEAT(FCVTLT_sd, aa64_sme_or_sve2, gen_gvec_fpst_arg_zpz, gen_helper_sve2_fcvtlt_sd, a, 0, FPST_A64) -- 2.43.0
Our implementation of the FLOGB insn does the operations entirely in the helper function, without needing to use fpu functions. This means it needs to handle all the fp status flags itself. We aren't setting float_flag_input_denormal_used when we use (i.e. do not flush to zero) an input denormal, which means that FPCR.IDC isn't set when it should be for FPCR.AH=1. We missed this when we added float_flag_input_denormal_used and made the fpu/ code set it. Add the missing float_raise(). Cc: qemu-stable@nongnu.org Fixes: d38a57a3f ("target/arm: Enable FEAT_AFP for '-cpu max'") Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260521122913.1565011-4-peter.maydell@linaro.org --- target/arm/tcg/sve_helper.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/arm/tcg/sve_helper.c b/target/arm/tcg/sve_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/sve_helper.c +++ b/target/arm/tcg/sve_helper.c @@ -XXX,XX +XXX,XX @@ static int16_t do_float16_logb_as_int(float16 a, float_status *s) if (frac != 0) { if (!get_flush_inputs_to_zero(s)) { /* denormal: bias - fractional_zeros */ + float_raise(float_flag_input_denormal_used, s); return -15 - clz32(frac); } /* flush to zero */ @@ -XXX,XX +XXX,XX @@ static int32_t do_float32_logb_as_int(float32 a, float_status *s) if (frac != 0) { if (!get_flush_inputs_to_zero(s)) { /* denormal: bias - fractional_zeros */ + float_raise(float_flag_input_denormal_used, s); return -127 - clz32(frac); } /* flush to zero */ @@ -XXX,XX +XXX,XX @@ static int64_t do_float64_logb_as_int(float64 a, float_status *s) if (frac != 0) { if (!get_flush_inputs_to_zero(s)) { /* denormal: bias - fractional_zeros */ + float_raise(float_flag_input_denormal_used, s); return -1023 - clz64(frac); } /* flush to zero */ -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-2-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpu-features.h | 9 +++++++++ target/arm/cpu-sysregs.h.inc | 1 + target/arm/cpu.c | 1 + target/arm/helper.c | 8 ++++++-- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64ISAR2, CSSC, 52, 4) FIELD(ID_AA64ISAR2, LUT, 56, 4) FIELD(ID_AA64ISAR2, ATS1A, 60, 4) +FIELD(ID_AA64ISAR3, CPA, 0, 4) +FIELD(ID_AA64ISAR3, FAMINMAX, 4, 4) +FIELD(ID_AA64ISAR3, TLBIW, 8, 4) +FIELD(ID_AA64ISAR3, PACM, 12, 4) +FIELD(ID_AA64ISAR3, LSFE, 16, 4) +FIELD(ID_AA64ISAR3, OCCMO, 20, 4) +FIELD(ID_AA64ISAR3, LSUI, 24, 4) +FIELD(ID_AA64ISAR3, FPRCVT, 28, 4) + FIELD(ID_AA64PFR0, EL0, 0, 4) FIELD(ID_AA64PFR0, EL1, 4, 4) FIELD(ID_AA64PFR0, EL2, 8, 4) diff --git a/target/arm/cpu-sysregs.h.inc b/target/arm/cpu-sysregs.h.inc index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu-sysregs.h.inc +++ b/target/arm/cpu-sysregs.h.inc @@ -XXX,XX +XXX,XX @@ DEF(ID_AA64AFR1_EL1, 3, 0, 0, 5, 5) DEF(ID_AA64ISAR0_EL1, 3, 0, 0, 6, 0) DEF(ID_AA64ISAR1_EL1, 3, 0, 0, 6, 1) DEF(ID_AA64ISAR2_EL1, 3, 0, 0, 6, 2) +DEF(ID_AA64ISAR3_EL1, 3, 0, 0, 6, 3) DEF(ID_AA64MMFR0_EL1, 3, 0, 0, 7, 0) DEF(ID_AA64MMFR1_EL1, 3, 0, 0, 7, 1) DEF(ID_AA64MMFR2_EL1, 3, 0, 0, 7, 2) 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_clear_aarch64_idregs(ARMCPU *cpu) SET_IDREG(&cpu->isar, ID_AA64ISAR0, 0); SET_IDREG(&cpu->isar, ID_AA64ISAR1, 0); SET_IDREG(&cpu->isar, ID_AA64ISAR2, 0); + SET_IDREG(&cpu->isar, ID_AA64ISAR3, 0); SET_IDREG(&cpu->isar, ID_AA64PFR0, 0); SET_IDREG(&cpu->isar, ID_AA64PFR1, 0); SET_IDREG(&cpu->isar, ID_AA64PFR2, 0); 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 register_cp_regs_for_features(ARMCPU *cpu) .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_tid3, .resetvalue = GET_IDREG(isar, ID_AA64ISAR2)}, - { .name = "ID_AA64ISAR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + { .name = "ID_AA64ISAR3_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 3, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_tid3, - .resetvalue = 0 }, + .resetvalue = GET_IDREG(isar, ID_AA64ISAR3) }, { .name = "ID_AA64ISAR4_EL1_RESERVED", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 4, .access = PL1_R, .type = ARM_CP_CONST, @@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu) R_ID_AA64ISAR2_BC_MASK | R_ID_AA64ISAR2_RPRFM_MASK | R_ID_AA64ISAR2_CSSC_MASK }, + { .name = "ID_AA64ISAR3_EL1", + .exported_bits = R_ID_AA64ISAR3_FAMINMAX_MASK | + R_ID_AA64ISAR3_LSFE_MASK | + R_ID_AA64ISAR3_FPRCVT_MASK }, { .name = "ID_AA64ISAR*_EL1_RESERVED", .is_glob = true }, }; -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20260522220306.235200-3-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpu-features.h | 5 +++++ target/arm/tcg/a64.decode | 5 +++++ target/arm/tcg/helper-a64-defs.h | 7 ++++++ target/arm/tcg/translate-a64.c | 14 ++++++++++++ target/arm/tcg/vec_helper64.c | 38 ++++++++++++++++++++++++++++++++ target/arm/tcg/vec_internal.h | 7 ++++++ 6 files changed, 76 insertions(+) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_ats1a(const ARMISARegisters *id) return FIELD_EX64_IDREG(id, ID_AA64ISAR2, ATS1A); } +static inline bool isar_feature_aa64_faminmax(const ARMISARegisters *id) +{ + return FIELD_EX64_IDREG(id, ID_AA64ISAR3, FAMINMAX) != 0; +} + static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id) { /* We always set the AdvSIMD and FP fields identically. */ diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/a64.decode +++ b/target/arm/tcg/a64.decode @@ -XXX,XX +XXX,XX @@ RSUBHN 0.10 1110 ..1 ..... 01100 0 ..... ..... @qrrr_e PMULL_p8 0.00 1110 001 ..... 11100 0 ..... ..... @qrrr_b PMULL_p64 0.00 1110 111 ..... 11100 0 ..... ..... @qrrr_b +FAMAX 0.00 1110 110 ..... 00011 1 ..... ..... @qrrr_h +FAMAX 0.00 1110 1.1 ..... 11011 1 ..... ..... @qrrr_sd +FAMIN 0.10 1110 110 ..... 00011 1 ..... ..... @qrrr_h +FAMIN 0.10 1110 1.1 ..... 11011 1 ..... ..... @qrrr_sd + ### Advanced SIMD scalar x indexed element FMUL_si 0101 1111 00 .. .... 1001 . 0 ..... ..... @rrx_h diff --git a/target/arm/tcg/helper-a64-defs.h b/target/arm/tcg/helper-a64-defs.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/helper-a64-defs.h +++ b/target/arm/tcg/helper-a64-defs.h @@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fmulx_idx_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, DEF_HELPER_FLAGS_5(gvec_fmulx_idx_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32) DEF_HELPER_FLAGS_5(gvec_fmulx_idx_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32) +DEF_HELPER_FLAGS_5(gvec_famax_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32) +DEF_HELPER_FLAGS_5(gvec_famin_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32) +DEF_HELPER_FLAGS_5(gvec_famax_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32) +DEF_HELPER_FLAGS_5(gvec_famin_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32) +DEF_HELPER_FLAGS_5(gvec_famax_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32) +DEF_HELPER_FLAGS_5(gvec_famin_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32) + #ifndef CONFIG_USER_ONLY DEF_HELPER_2(exception_return, void, env, i64) #endif diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-a64.c +++ b/target/arm/tcg/translate-a64.c @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3_ptr * const f_vector_fminnmp[3] = { }; TRANS(FMINNMP_v, do_fp3_vector, a, 0, f_vector_fminnmp) +static gen_helper_gvec_3_ptr * const f_vector_famax[3] = { + gen_helper_gvec_famax_h, + gen_helper_gvec_famax_s, + gen_helper_gvec_famax_d, +}; +TRANS_FEAT(FAMAX, aa64_faminmax, do_fp3_vector, a, 0, f_vector_famax) + +static gen_helper_gvec_3_ptr * const f_vector_famin[3] = { + gen_helper_gvec_famin_h, + gen_helper_gvec_famin_s, + gen_helper_gvec_famin_d, +}; +TRANS_FEAT(FAMIN, aa64_faminmax, do_fp3_vector, a, 0, f_vector_famin) + static bool do_fmlal(DisasContext *s, arg_qrrr_e *a, bool is_s, bool is_2) { if (fp_access_check(s)) { diff --git a/target/arm/tcg/vec_helper64.c b/target/arm/tcg/vec_helper64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/vec_helper64.c +++ b/target/arm/tcg/vec_helper64.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "cpu.h" +#include "internals.h" #include "helper.h" #include "helper-a64.h" #include "helper-sme.h" @@ -XXX,XX +XXX,XX @@ void HELPER(simd_tblx)(void *vd, void *vm, CPUARMState *env, uint32_t desc) memcpy(vd, &result, 16); clear_tail(vd, oprsz, simd_maxsz(desc)); } + +/* + * Use float_minmax_ismag to get the absolute value min/max. + * Avoid float_minmax_is{num,number} so that we get normal NaN processing. + * If the result is not a nan, take the absolute value. + * + * Note this operation squashes FZ, FIZ, and AH to 0. + */ +#define DO_FAMINMAX(NAME, TYPE, MIN) \ +TYPE TYPE##_##NAME(TYPE a, TYPE b, float_status *s) \ +{ \ + float_status local = *s; \ + set_flush_to_zero(false, &local); \ + set_flush_inputs_to_zero(false, &local); \ + arm_set_default_fp_behaviours(&local); \ + TYPE r = TYPE##_minmax(a, b, &local, MIN | float_minmax_ismag); \ + if (!TYPE##_is_any_nan(r)) { \ + r = TYPE##_abs(r); \ + } \ + float_raise(get_float_exception_flags(&local) \ + & ~float_flag_input_denormal_used, s); \ + return r; \ +} + +DO_FAMINMAX(famax, float16, 0) +DO_FAMINMAX(famin, float16, float_minmax_ismin) +DO_FAMINMAX(famax, float32, 0) +DO_FAMINMAX(famin, float32, float_minmax_ismin) +DO_FAMINMAX(famax, float64, 0) +DO_FAMINMAX(famin, float64, float_minmax_ismin) + +DO_3OP(gvec_famax_h, float16_famax, float16) +DO_3OP(gvec_famin_h, float16_famin, float16) +DO_3OP(gvec_famax_s, float32_famax, float32) +DO_3OP(gvec_famin_s, float32_famin, float32) +DO_3OP(gvec_famax_d, float64_famax, float64) +DO_3OP(gvec_famin_d, float64_famin, float64) diff --git a/target/arm/tcg/vec_internal.h b/target/arm/tcg/vec_internal.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/vec_internal.h +++ b/target/arm/tcg/vec_internal.h @@ -XXX,XX +XXX,XX @@ bfloat16 helper_sme2_ah_fmin_b16(bfloat16 a, bfloat16 b, float_status *fpst); float32 sve_f16_to_f32(float16 f, float_status *fpst); float16 sve_f32_to_f16(float32 f, float_status *fpst); +float16 float16_famax(float16, float16, float_status *); +float16 float16_famin(float16, float16, float_status *); +float32 float32_famax(float32, float32, float_status *); +float32 float32_famin(float32, float32, float_status *); +float64 float64_famax(float64, float64, float_status *); +float64 float64_famin(float64, float64, float_status *); + /* * Decode helper functions for predicate as counter. */ -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Since there is no bfloat16 variant of FAMINMAX, check for missing function pointer in do_z2z_nn_fpst. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-4-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpu-features.h | 5 +++++ target/arm/tcg/sme.decode | 5 +++++ target/arm/tcg/translate-sme.c | 23 +++++++++++++++++++++-- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_sme2_f64f64(const ARMISARegisters *id) return isar_feature_aa64_sme2(id) && isar_feature_aa64_sme_f64f64(id); } +static inline bool isar_feature_aa64_sme2_faminmax(const ARMISARegisters *id) +{ + return isar_feature_aa64_sme2(id) && isar_feature_aa64_faminmax(id); +} + static inline bool isar_feature_aa64_sve_i8mm(const ARMISARegisters *id) { return isar_feature_aa64_sve(id) && isar_feature_aa64_sme_sve_i8mm(id); diff --git a/target/arm/tcg/sme.decode b/target/arm/tcg/sme.decode index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/sme.decode +++ b/target/arm/tcg/sme.decode @@ -XXX,XX +XXX,XX @@ URSHL_nn 1100000 1 .. 1 ..... 1011.0 10001 .... 1 @z2z_4x4 SQDMULH_nn 1100000 1 .. 1 ..... 1011.1 00000 .... 0 @z2z_2x2 SQDMULH_nn 1100000 1 .. 1 ..... 1011.1 00000 .... 0 @z2z_4x4 +FAMAX_nn 1100000 1 .. 1 ..... 1011.0 01010 .... 0 @z2z_2x2 +FAMAX_nn 1100000 1 .. 1 ..... 1011.0 01010 .... 0 @z2z_4x4 +FAMIN_nn 1100000 1 .. 1 ..... 1011.0 01010 .... 1 @z2z_2x2 +FAMIN_nn 1100000 1 .. 1 ..... 1011.0 01010 .... 1 @z2z_4x4 + ### SME2 Multi-vector Multiple and Single Array Vectors &azz_n n off rv zn zm diff --git a/target/arm/tcg/translate-sme.c b/target/arm/tcg/translate-sme.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-sme.c +++ b/target/arm/tcg/translate-sme.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "cpu.h" +#include "helper-a64.h" #include "helper-sme.h" #include "helper-sve.h" #include "translate.h" @@ -XXX,XX +XXX,XX @@ static bool do_z2z_nn_fpst(DisasContext *s, arg_z2z_en *a, gen_helper_gvec_3_ptr * const fns[4]) { int esz = a->esz, n, dn, dm, vsz; - gen_helper_gvec_3_ptr *fn; + gen_helper_gvec_3_ptr *fn = fns[esz]; TCGv_ptr fpst; + if (fn == NULL) { + return false; + } if (esz == MO_8 && !dc_isar_feature(aa64_sme_b16b16, s)) { return false; } @@ -XXX,XX +XXX,XX @@ static bool do_z2z_nn_fpst(DisasContext *s, arg_z2z_en *a, } fpst = fpstatus_ptr(esz == MO_16 ? FPST_A64_F16 : FPST_A64); - fn = fns[esz]; n = a->n; dn = a->zdn; dm = a->zm; @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3_ptr * const f_vector_fminnm[4] = { TRANS_FEAT(FMINNM_n1, aa64_sme2, do_z2z_n1_fpst, a, f_vector_fminnm) TRANS_FEAT(FMINNM_nn, aa64_sme2, do_z2z_nn_fpst, a, f_vector_fminnm) +static gen_helper_gvec_3_ptr * const f_vector_famax[4] = { + NULL, + gen_helper_gvec_famax_h, + gen_helper_gvec_famax_s, + gen_helper_gvec_famax_d, +}; +TRANS_FEAT(FAMAX_nn, aa64_sme2_faminmax, do_z2z_nn_fpst, a, f_vector_famax) + +static gen_helper_gvec_3_ptr * const f_vector_famin[4] = { + NULL, + gen_helper_gvec_famin_h, + gen_helper_gvec_famin_s, + gen_helper_gvec_famin_d, +}; +TRANS_FEAT(FAMIN_nn, aa64_sme2_faminmax, do_z2z_nn_fpst, a, f_vector_famin) + /* Add/Sub vector Z[m] to each Z[n*N] with result in ZA[d*N]. */ static bool do_azz_n1(DisasContext *s, arg_azz_n *a, int esz, GVecGen3FnVar *fn) -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20260522220306.235200-5-richard.henderson@linaro.org [PMM: add comments for TRANS_ macros] Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpu-features.h | 11 +++++++++++ target/arm/tcg/helper-sve-defs.h | 14 ++++++++++++++ target/arm/tcg/sve.decode | 2 ++ target/arm/tcg/sve_helper.c | 8 ++++++++ target/arm/tcg/translate-sve.c | 20 ++++++++++++++++++++ target/arm/tcg/translate.h | 12 ++++++++++++ 6 files changed, 67 insertions(+) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_sme_or_sve2(const ARMISARegisters *id) return isar_feature_aa64_sme(id) || isar_feature_aa64_sve2(id); } +static inline bool isar_feature_aa64_sme2_or_sve2(const ARMISARegisters *id) +{ + return isar_feature_aa64_sme2(id) || isar_feature_aa64_sve2(id); +} + static inline bool isar_feature_aa64_sme_or_sve2p1(const ARMISARegisters *id) { return isar_feature_aa64_sme(id) || isar_feature_aa64_sve2p1(id); @@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_sve_bf16(const ARMISARegisters *id) return isar_feature_aa64_sve(id) && isar_feature_aa64_sme_sve_bf16(id); } +static inline bool +isar_feature_aa64_sme2_or_sve2_faminmax(const ARMISARegisters *id) +{ + return isar_feature_aa64_sme2_or_sve2(id) && isar_feature_aa64_faminmax(id); +} + /* * Feature tests for "does this exist in either 32-bit or 64-bit?" */ diff --git a/target/arm/tcg/helper-sve-defs.h b/target/arm/tcg/helper-sve-defs.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/helper-sve-defs.h +++ b/target/arm/tcg/helper-sve-defs.h @@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sve2p1_st1ss_le_c, TCG_CALL_NO_WG, void, env, ptr, tl, i32, i DEF_HELPER_FLAGS_5(sve2p1_st1ss_be_c, TCG_CALL_NO_WG, void, env, ptr, tl, i32, i64) DEF_HELPER_FLAGS_5(sve2p1_st1dd_le_c, TCG_CALL_NO_WG, void, env, ptr, tl, i32, i64) DEF_HELPER_FLAGS_5(sve2p1_st1dd_be_c, TCG_CALL_NO_WG, void, env, ptr, tl, i32, i64) + +DEF_HELPER_FLAGS_6(sve2_famax_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, fpst, i32) +DEF_HELPER_FLAGS_6(sve2_famax_s, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, fpst, i32) +DEF_HELPER_FLAGS_6(sve2_famax_d, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, fpst, i32) + +DEF_HELPER_FLAGS_6(sve2_famin_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, fpst, i32) +DEF_HELPER_FLAGS_6(sve2_famin_s, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, fpst, i32) +DEF_HELPER_FLAGS_6(sve2_famin_d, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, fpst, i32) diff --git a/target/arm/tcg/sve.decode b/target/arm/tcg/sve.decode index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/sve.decode +++ b/target/arm/tcg/sve.decode @@ -XXX,XX +XXX,XX @@ FSCALE 01100101 .. 00 1001 100 ... ..... ..... @rdn_pg_rm FMULX 01100101 .. 00 1010 100 ... ..... ..... @rdn_pg_rm FDIV 01100101 .. 00 1100 100 ... ..... ..... @rdm_pg_rn # FDIVR FDIV 01100101 .. 00 1101 100 ... ..... ..... @rdn_pg_rm +FAMAX 01100101 .. 00 1110 100 ... ..... ..... @rdn_pg_rm +FAMIN 01100101 .. 00 1111 100 ... ..... ..... @rdn_pg_rm # SVE floating-point arithmetic with immediate (predicated) FADD_zpzi 01100101 .. 011 000 100 ... 0000 . ..... @rdn_i1 diff --git a/target/arm/tcg/sve_helper.c b/target/arm/tcg/sve_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/sve_helper.c +++ b/target/arm/tcg/sve_helper.c @@ -XXX,XX +XXX,XX @@ DO_ZPZZ_FP(sve_fmulx_h, uint16_t, H1_2, helper_advsimd_mulxh) DO_ZPZZ_FP(sve_fmulx_s, uint32_t, H1_4, helper_vfp_mulxs) DO_ZPZZ_FP(sve_fmulx_d, uint64_t, H1_8, helper_vfp_mulxd) +DO_ZPZZ_FP(sve2_famax_h, uint16_t, H1_2, float16_famax) +DO_ZPZZ_FP(sve2_famax_s, uint32_t, H1_4, float32_famax) +DO_ZPZZ_FP(sve2_famax_d, uint64_t, H1_8, float64_famax) + +DO_ZPZZ_FP(sve2_famin_h, uint16_t, H1_2, float16_famin) +DO_ZPZZ_FP(sve2_famin_s, uint32_t, H1_4, float32_famin) +DO_ZPZZ_FP(sve2_famin_d, uint64_t, H1_8, float64_famin) + #undef DO_ZPZZ_FP /* Three-operand expander, with one scalar operand, controlled by diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-sve.c +++ b/target/arm/tcg/translate-sve.c @@ -XXX,XX +XXX,XX @@ DO_ZPZZ_FP(FSCALE, aa64_sme_or_sve, sve_fscalbn) DO_ZPZZ_FP(FDIV, aa64_sme_or_sve, sve_fdiv) DO_ZPZZ_FP(FMULX, aa64_sme_or_sve, sve_fmulx) +static gen_helper_gvec_4_ptr * const sve2_famax_zpzz_fns[4] = { + NULL, + gen_helper_sve2_famax_h, + gen_helper_sve2_famax_s, + gen_helper_sve2_famax_d +}; +TRANS_FEAT_STREAMING_SME2(FAMAX, aa64_sme2_or_sve2_faminmax, + gen_gvec_fpst_arg_zpzz, + sve2_famax_zpzz_fns[a->esz], a) + +static gen_helper_gvec_4_ptr * const sve2_famin_zpzz_fns[4] = { + NULL, + gen_helper_sve2_famin_h, + gen_helper_sve2_famin_s, + gen_helper_sve2_famin_d +}; +TRANS_FEAT_STREAMING_SME2(FAMIN, aa64_sme2_or_sve2_faminmax, + gen_gvec_fpst_arg_zpzz, + sve2_famin_zpzz_fns[a->esz], a) + typedef void gen_helper_sve_fp2scalar(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv_ptr, TCGv_i32); diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate.h +++ b/target/arm/tcg/translate.h @@ -XXX,XX +XXX,XX @@ static inline void gen_restore_rmode(TCGv_i32 old, TCGv_ptr fpst) static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \ { return dc_isar_feature(FEAT, s) && FUNC(s, __VA_ARGS__); } +/* For SVE insns which are not valid in Streaming SVE mode */ #define TRANS_FEAT_NONSTREAMING(NAME, FEAT, FUNC, ...) \ static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \ { \ @@ -XXX,XX +XXX,XX @@ static inline void gen_restore_rmode(TCGv_i32 old, TCGv_ptr fpst) return dc_isar_feature(FEAT, s) && FUNC(s, __VA_ARGS__); \ } +/* + * For SVE insns which are only valid in Streaming SVE mode when + * SME2 is implemented + */ +#define TRANS_FEAT_STREAMING_SME2(NAME, FEAT, FUNC, ...) \ + static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \ + { \ + s->is_nonstreaming = !dc_isar_feature(aa64_sme2, s); \ + return dc_isar_feature(FEAT, s) && FUNC(s, __VA_ARGS__); \ + } + #endif /* TARGET_ARM_TRANSLATE_H */ -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-6-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- docs/system/arm/emulation.rst | 1 + linux-user/aarch64/elfload.c | 1 + target/arm/tcg/cpu64.c | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/system/arm/emulation.rst +++ b/docs/system/arm/emulation.rst @@ -XXX,XX +XXX,XX @@ the following architecture extensions: - FEAT_EVT (Enhanced Virtualization Traps) - FEAT_F32MM (Single-precision Matrix Multiplication) - FEAT_F64MM (Double-precision Matrix Multiplication) +- FEAT_FAMINMAX (Floating-point maximum and minimum absolute value instructions) - FEAT_FCMA (Floating-point complex number instructions) - FEAT_FGT (Fine-Grained Traps) - FEAT_FHM (Floating-point half-precision multiplication instructions) diff --git a/linux-user/aarch64/elfload.c b/linux-user/aarch64/elfload.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/aarch64/elfload.c +++ b/linux-user/aarch64/elfload.c @@ -XXX,XX +XXX,XX @@ abi_ulong get_elf_hwcap2(CPUState *cs) GET_FEATURE_ID(aa64_sve_b16b16, ARM_HWCAP2_A64_SVE_B16B16); GET_FEATURE_ID(aa64_cssc, ARM_HWCAP2_A64_CSSC); GET_FEATURE_ID(aa64_lse128, ARM_HWCAP2_A64_LSE128); + GET_FEATURE_ID(aa64_faminmax, ARM_HWCAP2_A64_FAMINMAX); return hwcaps; } diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/cpu64.c +++ b/target/arm/tcg/cpu64.c @@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64ISAR2, ATS1A, 1); /* FEAT_ATS1A */ SET_IDREG(isar, ID_AA64ISAR2, t); + t = GET_IDREG(isar, ID_AA64ISAR3); + t = FIELD_DP64(t, ID_AA64ISAR3, FAMINMAX, 1); /* FEAT_FAMINMAX */ + SET_IDREG(isar, ID_AA64ISAR3, t); + t = GET_IDREG(isar, ID_AA64PFR0); t = FIELD_DP64(t, ID_AA64PFR0, FP, 1); /* FEAT_FP16 */ t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1); /* FEAT_FP16 */ -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-7-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpu.h | 11 +++++++++++ 1 file changed, 11 insertions(+) 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 void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) #define SCR_AIEN (1ULL << 46) #define SCR_GPF (1ULL << 48) #define SCR_MECEN (1ULL << 49) +#define SCR_ENFPM (1ULL << 50) +#define SCR_TMEA (1ULL << 51) +#define SCR_TWERR (1ULL << 52) +#define SCR_PFAREN (1ULL << 53) +#define SCR_SRMASKEN (1ULL << 54) +#define SCR_ENIDCP128 (1ULL << 55) +#define SCR_DSE (1ULL << 57) +#define SCR_ENDSE (1ULL << 58) +#define SCR_FGTEN2 (1ULL << 59) +#define SCR_HDBSSEN (1ULL << 60) +#define SCR_HACDBSEN (1ULL << 61) #define SCR_NSE (1ULL << 62) /* GCSCR_ELx fields */ -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-8-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/internals.h | 3 +++ 1 file changed, 3 insertions(+) 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 @@ FIELD(VSTCR, SA, 30, 1) #define HCRX_TCR2EN (1ULL << 14) #define HCRX_SCTLR2EN (1ULL << 15) #define HCRX_GCSEN (1ULL << 22) +#define HCRX_ENFPM (1ULL << 23) +#define HCRX_PACMEN (1ULL << 24) +#define HCRX_SRMASKEN (1ULL << 26) #define HPFAR_NS (1ULL << 63) -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Introduce the special register FPMR and its fields. Migrate it when present. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-9-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpregs.h | 5 +++++ target/arm/cpu-features.h | 5 +++++ target/arm/cpu.h | 1 + target/arm/helper.c | 12 +++++++++++- target/arm/internals.h | 10 ++++++++++ target/arm/machine.c | 20 ++++++++++++++++++++ 6 files changed, 52 insertions(+), 1 deletion(-) diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpregs.h +++ b/target/arm/cpregs.h @@ -XXX,XX +XXX,XX @@ enum { * should not trap to EL2 when HCR_EL2.NV is set. */ ARM_CP_NV_NO_TRAP = 1 << 22, + /* + * Flag: Access check for this sysreg is constrained by the + * ARM pseudocode function CheckFPMREnabled(). + */ + ARM_CP_FPMR = 1 << 23, }; /* diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_gcie(const ARMISARegisters *id) return FIELD_EX64_IDREG(id, ID_AA64PFR2, GCIE) != 0; } +static inline bool isar_feature_aa64_fpmr(const ARMISARegisters *id) +{ + return FIELD_EX64_IDREG(id, ID_AA64PFR2, FPMR) != 0; +} + static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id) { return FIELD_SEX64_IDREG(id, ID_AA64MMFR0, TGRAN4) >= 1; 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 CPUArchState { */ uint64_t fpsr; uint64_t fpcr; + uint64_t fpmr; uint32_t xregs[16]; 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 const ARMCPRegInfo aie_reginfo[] = { .type = ARM_CP_CONST, .resetvalue = 0 }, }; +static const ARMCPRegInfo fpmr_reginfo[] = { + { .name = "FPMR", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 4, .opc2 = 2, + .access = PL0_RW, .type = ARM_CP_FPU | ARM_CP_FPMR, + .fieldoffset = offsetof(CPUARMState, vfp.fpmr), + } +}; + void register_cp_regs_for_features(ARMCPU *cpu) { /* Register all the coprocessor registers based on feature bits */ @@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu) define_arm_cp_regs(cpu, mec_mte_reginfo); } } - if (cpu_isar_feature(aa64_aie, cpu)) { define_arm_cp_regs(cpu, aie_reginfo); } + if (cpu_isar_feature(aa64_fpmr, cpu)) { + define_arm_cp_regs(cpu, fpmr_reginfo); + } if (cpu_isar_feature(any_predinv, cpu)) { define_arm_cp_regs(cpu, predinv_reginfo); 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 @@ FIELD(CNTHCTL, EVNTIS, 17, 1) FIELD(CNTHCTL, CNTVMASK, 18, 1) FIELD(CNTHCTL, CNTPMASK, 19, 1) +FIELD(FPMR, F8S1, 0, 3) +FIELD(FPMR, F8S2, 3, 3) +FIELD(FPMR, F8D, 6, 3) +FIELD(FPMR, OSM, 14, 1) +FIELD(FPMR, OSC, 15, 1) +FIELD(FPMR, LSCALE, 16, 7) +FIELD(FPMR, NSCALE, 24, 8) +FIELD(FPMR, NSCALE_F16, 24, 5) +FIELD(FPMR, LSCALE2, 32, 6) + /* We use a few fake FSR values for internal purposes in M profile. * M profile cores don't have A/R format FSRs, but currently our * get_phys_addr() code assumes A/R profile and reports failures via 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 const VMStateDescription vmstate_syndrome64 = { }, }; +static bool fpmr_needed(void *opaque) +{ + ARMCPU *cpu = opaque; + + return arm_feature(&cpu->env, ARM_FEATURE_AARCH64) + && cpu_isar_feature(aa64_fpmr, cpu); +} + +static const VMStateDescription vmstate_fpmr = { + .name = "cpu/fpmr", + .version_id = 1, + .minimum_version_id = 1, + .needed = fpmr_needed, + .fields = (const VMStateField[]) { + VMSTATE_UINT64(env.vfp.fpmr, ARMCPU), + VMSTATE_END_OF_LIST() + }, +}; + static int cpu_pre_save(void *opaque) { ARMCPU *cpu = opaque; @@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_arm_cpu = { &vmstate_syndrome64, &vmstate_pstate64, &vmstate_event, + &vmstate_fpmr, NULL } }; -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-10-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpu.h | 1 + 1 file changed, 1 insertion(+) 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 pmu_init(ARMCPU *cpu); #define SCTLR_DSSBS_32 (1U << 31) /* v8.5, AArch32 only */ #define SCTLR_CMOW (1ULL << 32) /* FEAT_CMOW */ #define SCTLR_MSCEN (1ULL << 33) /* FEAT_MOPS */ +#define SCTLR_EnFPM (1ULL << 34) /* FEAT_FPMR */ #define SCTLR_BT0 (1ULL << 35) /* v8.5-BTI */ #define SCTLR_BT1 (1ULL << 36) /* v8.5-BTI */ #define SCTLR_ITFSB (1ULL << 37) /* v8.5-MemTag */ -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-11-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpu.c | 3 +++ target/arm/helper.c | 9 +++++++++ 2 files changed, 12 insertions(+) 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 @@ void arm_emulate_firmware_reset(CPUState *cpustate, int target_el) if (cpu_isar_feature(aa64_mec, cpu)) { env->cp15.scr_el3 |= SCR_MECEN; } + if (cpu_isar_feature(aa64_fpmr, cpu)) { + env->cp15.scr_el3 |= SCR_ENFPM; + } } if (target_el == 2) { 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 scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) if (cpu_isar_feature(aa64_mec, cpu)) { valid_mask |= SCR_MECEN; } + if (cpu_isar_feature(aa64_fpmr, cpu)) { + valid_mask |= SCR_ENFPM; + } } else { valid_mask &= ~(SCR_RW | SCR_ST); if (cpu_isar_feature(aa32_ras, cpu)) { @@ -XXX,XX +XXX,XX @@ static void hcrx_write(CPUARMState *env, const ARMCPRegInfo *ri, if (cpu_isar_feature(aa64_gcs, cpu)) { valid_mask |= HCRX_GCSEN; } + if (cpu_isar_feature(aa64_fpmr, cpu)) { + valid_mask |= HCRX_ENFPM; + } /* Clear RES0 bits. */ env->cp15.hcrx_el2 = value & valid_mask; @@ -XXX,XX +XXX,XX @@ uint64_t arm_hcrx_el2_eff(CPUARMState *env) if (cpu_isar_feature(aa64_gcs, cpu)) { hcrx |= HCRX_GCSEN; } + if (cpu_isar_feature(aa64_fpmr, cpu)) { + hcrx |= HCRX_ENFPM; + } return hcrx; } if (arm_feature(env, ARM_FEATURE_EL3) && !(env->cp15.scr_el3 & SCR_HXEN)) { -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> FPMR is cleared when entering or exiting Streaming Mode. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-12-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper.c | 1 + 1 file changed, 1 insertion(+) 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 arm_reset_sve_state(CPUARMState *env) /* Recall that FFR is stored as pregs[16]. */ memset(env->vfp.pregs, 0, sizeof(env->vfp.pregs)); vfp_set_fpsr(env, 0x0800009f); + env->vfp.fpmr = 0; } void aarch64_set_svcr(CPUARMState *env, uint64_t new, uint64_t mask) -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Prepare to perform access checks for direct and indirect uses of FPMR. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-13-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpu.h | 1 + target/arm/tcg/hflags.c | 42 ++++++++++++++++++++++++++++++++++ target/arm/tcg/translate-a64.c | 1 + target/arm/tcg/translate.h | 2 ++ 4 files changed, 46 insertions(+) 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_A64, ZT0EXC_EL, 39, 2) FIELD(TBFLAG_A64, GCS_EN, 41, 1) FIELD(TBFLAG_A64, GCS_RVCEN, 42, 1) FIELD(TBFLAG_A64, GCSSTR_EL, 43, 2) +FIELD(TBFLAG_A64, FPMR_EL, 45, 2) /* * Helpers for using the above. Note that only the A64 accessors use diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/hflags.c +++ b/target/arm/tcg/hflags.c @@ -XXX,XX +XXX,XX @@ static int zt0_exception_el(CPUARMState *env, int el) return 0; } +/* + * Return the exception level to which exceptions should be taken for FPMR. + * Compare the EnFPM bits in the "Accessing FPMR" pseudocode. Note that + * the floating-point enabled check will be handled separately. + */ +static int fpmr_exception_el(CPUARMState *env, int el) +{ + switch (el) { + case 0: + if (el_is_in_host(env, 0)) { + if (!(env->cp15.sctlr_el[2] & SCTLR_EnFPM)) { + return 2; + } + break; + } + if (!(env->cp15.sctlr_el[1] & SCTLR_EnFPM)) { + return 1; + } + /* fall through */ + case 1: + if (!(arm_hcrx_el2_eff(env) & HCRX_ENFPM)) { + return 2; + } + break; + case 2: + break; + case 3: + return 0; + default: + g_assert_not_reached(); + } + if (arm_feature(env, ARM_FEATURE_EL3) + && !(env->cp15.scr_el3 & SCR_ENFPM)) { + return 3; + } + return 0; +} + static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, ARMMMUIdx mmu_idx) { @@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, } } + if (cpu_isar_feature(aa64_fpmr, env_archcpu(env))) { + DP_TBFLAG_A64(flags, FPMR_EL, fpmr_exception_el(env, el)); + } + return rebuild_hflags_common(env, fp_el, mmu_idx, flags); } diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-a64.c +++ b/target/arm/tcg/translate-a64.c @@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase, dc->gcs_en = EX_TBFLAG_A64(tb_flags, GCS_EN); dc->gcs_rvcen = EX_TBFLAG_A64(tb_flags, GCS_RVCEN); dc->gcsstr_el = EX_TBFLAG_A64(tb_flags, GCSSTR_EL); + dc->fpmr_el = EX_TBFLAG_A64(tb_flags, FPMR_EL); dc->vec_len = 0; dc->vec_stride = 0; dc->cp_regs = arm_cpu->cp_regs; diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate.h +++ b/target/arm/tcg/translate.h @@ -XXX,XX +XXX,XX @@ typedef struct DisasContext { uint8_t gm_blocksize; /* True if the current insn_start has been updated. */ bool insn_start_updated; + /* FPMR access exception EL or 0 if enabled. */ + uint8_t fpmr_el; /* Offset from VNCR_EL2 when FEAT_NV2 redirects this reg to memory */ uint32_t nv2_redirect_offset; } DisasContext; -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-14-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/tcg/translate-a64.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-a64.c +++ b/target/arm/tcg/translate-a64.c @@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, bool isread, } if (!skip_fp_access_checks) { + if ((ri->type & ARM_CP_FPMR) && s->fpmr_el != 0) { + gen_exception_insn_el(s, 0, EXCP_UDEF, syndrome, s->fpmr_el); + return; + } if ((ri->type & ARM_CP_FPU) && !fp_access_check_only(s)) { return; } else if ((ri->type & ARM_CP_SVE) && !sve_access_check(s)) { -- 2.43.0
From: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com> As well, use -smp 1 since there is no visible speedup running with -smp 2. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-15-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- tests/functional/aarch64/test_rme_sbsaref.py | 7 ++++--- tests/functional/aarch64/test_rme_virt.py | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/functional/aarch64/test_rme_sbsaref.py b/tests/functional/aarch64/test_rme_sbsaref.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/aarch64/test_rme_sbsaref.py +++ b/tests/functional/aarch64/test_rme_sbsaref.py @@ -XXX,XX +XXX,XX @@ class Aarch64RMESbsaRefMachine(QemuSystemTest): # Stack is inspired from: # https://linaro.atlassian.net/wiki/spaces/QEMU/pages/29051027459/ + # Built from: # https://github.com/p-b-o/qemu-linux-stack/tree/rme_sbsa_release # ./build.sh && ./archive_artifacts.sh out.tar.xz ASSET_RME_STACK_SBSA = Asset( ('https://github.com/p-b-o/qemu-linux-stack/' - 'releases/download/build/rme_sbsa_release-6a2dfc5.tar.xz'), - '5adba482aa069912292a8da746c6b21268224d9d81c97fe7c0bed690579ebdcb') + 'releases/download/build/rme_sbsa_release-74b7fab.tar.xz'), + '82a754bacea04e709cb1cf2759d1d12d09fabd612e014961eb32368723c7920a') # This tests the FEAT_RME cpu implementation, by booting a VM supporting it, # and launching a nested VM using it. @@ -XXX,XX +XXX,XX @@ def test_aarch64_rme_sbsaref(self): ' --params "root=/dev/vda rw init=/init"') self.vm.add_args('-cpu', 'max,x-rme=on') - self.vm.add_args('-smp', '2') + self.vm.add_args('-smp', '1') self.vm.add_args('-m', '2G') self.vm.add_args('-M', 'sbsa-ref') self.vm.add_args('-drive', f'file={pflash0},format=raw,if=pflash') diff --git a/tests/functional/aarch64/test_rme_virt.py b/tests/functional/aarch64/test_rme_virt.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/aarch64/test_rme_virt.py +++ b/tests/functional/aarch64/test_rme_virt.py @@ -XXX,XX +XXX,XX @@ class Aarch64RMEVirtMachine(QemuSystemTest): # Stack is inspired from: # https://linaro.atlassian.net/wiki/spaces/QEMU/pages/29051027459/ + # Built from: # https://github.com/p-b-o/qemu-linux-stack/tree/rme_release # ./build.sh && ./archive_artifacts.sh out.tar.xz ASSET_RME_STACK_VIRT = Asset( ('https://github.com/p-b-o/qemu-linux-stack/' - 'releases/download/build/rme_release-56bc99e.tar.xz'), - '0e3dc6b8a4b828dbae09c951a40dcb710eded084b32432b50c69cf4173ffa4be') + 'releases/download/build/rme_release-2701e89.tar.xz'), + '8c40af440f5bd1518f7add7d0a43b39289865ee48430979db8024cb897a74790') # This tests the FEAT_RME cpu implementation, by booting a VM supporting it, # and launching a nested VM using it. @@ -XXX,XX +XXX,XX @@ def test_aarch64_rme_virt(self): rootfs = join(rme_stack, 'out', 'host.ext4') self.vm.add_args('-cpu', 'max,x-rme=on') - self.vm.add_args('-smp', '2') + self.vm.add_args('-smp', '1') self.vm.add_args('-m', '2G') self.vm.add_args('-M', 'virt,acpi=off,' 'virtualization=on,' -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-16-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags) qemu_fprintf(f, " FPU disabled\n"); return; } - qemu_fprintf(f, " FPCR=%08x FPSR=%08x\n", + qemu_fprintf(f, " FPCR=%08x FPSR=%08x", vfp_get_fpcr(env), vfp_get_fpsr(env)); + if (cpu_isar_feature(aa64_fpmr, cpu)) { + qemu_fprintf(f, " FPMR=0x%" PRIx64, env->vfp.fpmr); + } + qemu_fprintf(f, "\n"); if (cpu_isar_feature(aa64_sme, cpu) && FIELD_EX64(env->svcr, SVCR, SM)) { sve = sme_exception_el(env, el) == 0; -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-17-richard.henderson@linaro.org Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- linux-user/aarch64/signal.c | 44 ++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/aarch64/signal.c +++ b/linux-user/aarch64/signal.c @@ -XXX,XX +XXX,XX @@ struct target_esr_context { uint64_t esr; }; +#define TARGET_FPMR_MAGIC 0x46504d52 + +struct target_fpmr_context { + struct target_aarch64_ctx head; + uint64_t fpmr; +}; + #define TARGET_EXTRA_MAGIC 0x45585401 struct target_extra_context { @@ -XXX,XX +XXX,XX @@ static bool target_setup_gcs_record(struct target_gcs_context *ctx, return true; } +static void target_setup_fpmr_record(struct target_fpmr_context *ctx, + CPUARMState *env) +{ + __put_user(TARGET_FPMR_MAGIC, &ctx->head.magic); + __put_user(sizeof(*ctx), &ctx->head.size); + __put_user(env->vfp.fpmr, &ctx->fpmr); +} + static void target_restore_general_frame(CPUARMState *env, struct target_rt_sigframe *sf) { @@ -XXX,XX +XXX,XX @@ static void target_restore_tpidr2_record(CPUARMState *env, __get_user(env->cp15.tpidr2_el0, &tpidr2->tpidr2); } +static void target_restore_fpmr_record(CPUARMState *env, + struct target_fpmr_context *fpmr) +{ + __get_user(env->vfp.fpmr, &fpmr->fpmr); +} + static bool target_restore_zt_record(CPUARMState *env, struct target_zt_context *zt, int size, int svcr) @@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env, struct target_tpidr2_context *tpidr2 = NULL; struct target_zt_context *zt = NULL; struct target_gcs_context *gcs = NULL; + struct target_fpmr_context *fpmr = NULL; uint64_t extra_datap = 0; bool used_extra = false; bool rebuild_hflags = false; @@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env, gcs = (struct target_gcs_context *)ctx; break; + case TARGET_FPMR_MAGIC: + if (fpmr + || size != sizeof(struct target_fpmr_context) + || !cpu_isar_feature(aa64_fpmr, env_archcpu(env))) { + goto err; + } + fpmr = (struct target_fpmr_context *)ctx; + break; + case TARGET_EXTRA_MAGIC: if (extra || size != sizeof(struct target_extra_context)) { goto err; @@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env, if (tpidr2) { target_restore_tpidr2_record(env, tpidr2); } + if (fpmr) { + target_restore_fpmr_record(env, fpmr); + } /* * NB that we must restore ZT after ZA so the check that there's * no ZT record if SVCR.ZA is 0 gets the right value of SVCR. @@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka, uc.tuc_mcontext.__reserved), }; int fpsimd_ofs, fr_ofs, sve_ofs = 0, za_ofs = 0, tpidr2_ofs = 0; - int zt_ofs = 0, esr_ofs = 0, gcs_ofs = 0; + int zt_ofs = 0, esr_ofs = 0, gcs_ofs = 0, fpmr_ofs = 0; int sve_size = 0, za_size = 0, tpidr2_size = 0, zt_size = 0; struct target_rt_sigframe *frame; struct target_rt_frame_record *fr; @@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka, &layout); } + if (cpu_isar_feature(aa64_fpmr, env_archcpu(env))) { + fpmr_ofs = alloc_sigframe_space(sizeof(struct target_fpmr_context), + &layout); + } + /* SVE state needs saving only if it exists. */ if (cpu_isar_feature(aa64_sve, env_archcpu(env)) || cpu_isar_feature(aa64_sme, env_archcpu(env))) { @@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka, !target_setup_gcs_record((void *)frame + gcs_ofs, env, return_addr)) { goto give_sigsegv; } + if (fpmr_ofs) { + target_setup_fpmr_record((void *)frame + fpmr_ofs, env); + } target_setup_end_record((void *)frame + layout.std_end_ofs); if (layout.extra_ofs) { target_setup_extra_record((void *)frame + layout.extra_ofs, -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-18-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- docs/system/arm/emulation.rst | 1 + linux-user/aarch64/elfload.c | 1 + target/arm/tcg/cpu64.c | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/system/arm/emulation.rst +++ b/docs/system/arm/emulation.rst @@ -XXX,XX +XXX,XX @@ the following architecture extensions: - FEAT_FPAC (Faulting on AUT* instructions) - FEAT_FPACCOMBINE (Faulting on combined pointer authentication instructions) - FEAT_FPACC_SPEC (Speculative behavior of combined pointer authentication instructions) +- FEAT_FPMR (Floating-point Mode Register) - FEAT_FRINTTS (Floating-point to integer instructions) - FEAT_FlagM (Flag manipulation instructions v2) - FEAT_FlagM2 (Enhancements to flag manipulation instructions) diff --git a/linux-user/aarch64/elfload.c b/linux-user/aarch64/elfload.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/aarch64/elfload.c +++ b/linux-user/aarch64/elfload.c @@ -XXX,XX +XXX,XX @@ abi_ulong get_elf_hwcap2(CPUState *cs) GET_FEATURE_ID(aa64_cssc, ARM_HWCAP2_A64_CSSC); GET_FEATURE_ID(aa64_lse128, ARM_HWCAP2_A64_LSE128); GET_FEATURE_ID(aa64_faminmax, ARM_HWCAP2_A64_FAMINMAX); + GET_FEATURE_ID(aa64_fpmr, ARM_HWCAP2_A64_FPMR); return hwcaps; } diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/cpu64.c +++ b/target/arm/tcg/cpu64.c @@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64PFR1, GCS, 1); /* FEAT_GCS */ SET_IDREG(isar, ID_AA64PFR1, t); + t = GET_IDREG(isar, ID_AA64PFR2); + t = FIELD_DP64(t, ID_AA64PFR2, FPMR, 1); /* FEAT_FPMR */ + SET_IDREG(isar, ID_AA64PFR2, t); + t = GET_IDREG(isar, ID_AA64MMFR0); t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 6); /* FEAT_LPA: 52 bits */ t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16, 1); /* 16k pages supported */ -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-19-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpu-features.h | 9 +++++++++ target/arm/cpu-sysregs.h.inc | 1 + target/arm/cpu.c | 1 + target/arm/helper.c | 13 +++++++++++-- 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64SMFR0, I16I64, 52, 4) FIELD(ID_AA64SMFR0, SMEVER, 56, 4) FIELD(ID_AA64SMFR0, FA64, 63, 1) +FIELD(ID_AA64FPFR0, F8E5M2, 0, 1) +FIELD(ID_AA64FPFR0, F8E4M3, 1, 1) +FIELD(ID_AA64FPFR0, F8MM4, 26, 1) +FIELD(ID_AA64FPFR0, F8MM8, 27, 1) +FIELD(ID_AA64FPFR0, F8DP2, 28, 1) +FIELD(ID_AA64FPFR0, F8DP4, 29, 1) +FIELD(ID_AA64FPFR0, F8FMA, 30, 1) +FIELD(ID_AA64FPFR0, F8CVT, 31, 1) + FIELD(ID_DFR0, COPDBG, 0, 4) FIELD(ID_DFR0, COPSDBG, 4, 4) FIELD(ID_DFR0, MMAPDBG, 8, 4) diff --git a/target/arm/cpu-sysregs.h.inc b/target/arm/cpu-sysregs.h.inc index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu-sysregs.h.inc +++ b/target/arm/cpu-sysregs.h.inc @@ -XXX,XX +XXX,XX @@ DEF(ID_AA64PFR0_EL1, 3, 0, 0, 4, 0) DEF(ID_AA64PFR1_EL1, 3, 0, 0, 4, 1) DEF(ID_AA64PFR2_EL1, 3, 0, 0, 4, 2) DEF(ID_AA64SMFR0_EL1, 3, 0, 0, 4, 5) +DEF(ID_AA64FPFR0_EL1, 3, 0, 0, 4, 7) DEF(ID_AA64DFR0_EL1, 3, 0, 0, 5, 0) DEF(ID_AA64DFR1_EL1, 3, 0, 0, 5, 1) DEF(ID_AA64AFR0_EL1, 3, 0, 0, 5, 4) 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_clear_aarch64_idregs(ARMCPU *cpu) SET_IDREG(&cpu->isar, ID_AA64AFR1, 0); SET_IDREG(&cpu->isar, ID_AA64ZFR0, 0); SET_IDREG(&cpu->isar, ID_AA64SMFR0, 0); + SET_IDREG(&cpu->isar, ID_AA64FPFR0, 0); } static void arm_cpu_realizefn(DeviceState *dev, Error **errp) 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 register_cp_regs_for_features(ARMCPU *cpu) .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_tid3, .resetvalue = 0 }, - { .name = "ID_AA64PFR7_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + { .name = "ID_AA64FPFR0_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 7, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_tid3, - .resetvalue = 0 }, + .resetvalue = GET_IDREG(isar, ID_AA64FPFR0) }, { .name = "ID_AA64DFR0_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 0, .access = PL1_R, .type = ARM_CP_CONST, @@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu) R_ID_AA64SMFR0_I16I64_MASK | R_ID_AA64SMFR0_SMEVER_MASK | R_ID_AA64SMFR0_FA64_MASK }, + { .name = "ID_AA64FPFR0_EL1", + .exported_bits = R_ID_AA64FPFR0_F8E5M2_MASK | + R_ID_AA64FPFR0_F8E4M3_MASK | + R_ID_AA64FPFR0_F8MM4_MASK | + R_ID_AA64FPFR0_F8MM8_MASK | + R_ID_AA64FPFR0_F8DP2_MASK | + R_ID_AA64FPFR0_F8DP4_MASK | + R_ID_AA64FPFR0_F8FMA_MASK | + R_ID_AA64FPFR0_F8CVT_MASK }, { .name = "ID_AA64MMFR0_EL1", .exported_bits = R_ID_AA64MMFR0_ECV_MASK, .fixed_bits = (0xfu << R_ID_AA64MMFR0_TGRAN64_SHIFT) | -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-20-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpu-features.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_sme2p1(const ARMISARegisters *id) return FIELD_EX64_IDREG(id, ID_AA64SMFR0, SMEVER) >= 2; } +static inline bool isar_feature_aa64_f8cvt(const ARMISARegisters *id) +{ + return FIELD_EX64_IDREG(id, ID_AA64FPFR0, F8CVT); +} + /* * Combinations of feature tests, for ease of use with TRANS_FEAT. */ -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-21-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/tcg/a64.decode | 3 +++ target/arm/tcg/helper-a64-defs.h | 4 ++++ target/arm/tcg/sve_helper.c | 6 ------ target/arm/tcg/translate-a64.c | 7 +++++++ target/arm/tcg/vec_helper64.c | 4 ++++ target/arm/tcg/vec_internal.h | 6 ++++++ 6 files changed, 24 insertions(+), 6 deletions(-) diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/a64.decode +++ b/target/arm/tcg/a64.decode @@ -XXX,XX +XXX,XX @@ FAMAX 0.00 1110 1.1 ..... 11011 1 ..... ..... @qrrr_sd FAMIN 0.10 1110 110 ..... 00011 1 ..... ..... @qrrr_h FAMIN 0.10 1110 1.1 ..... 11011 1 ..... ..... @qrrr_sd +FSCALE 0.10 1110 110 ..... 00111 1 ..... ..... @qrrr_h +FSCALE 0.10 1110 1.1 ..... 11111 1 ..... ..... @qrrr_sd + ### Advanced SIMD scalar x indexed element FMUL_si 0101 1111 00 .. .... 1001 . 0 ..... ..... @rrx_h diff --git a/target/arm/tcg/helper-a64-defs.h b/target/arm/tcg/helper-a64-defs.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/helper-a64-defs.h +++ b/target/arm/tcg/helper-a64-defs.h @@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_famin_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32 DEF_HELPER_FLAGS_5(gvec_famax_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32) DEF_HELPER_FLAGS_5(gvec_famin_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32) +DEF_HELPER_FLAGS_5(gvec_fscale_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32) +DEF_HELPER_FLAGS_5(gvec_fscale_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32) +DEF_HELPER_FLAGS_5(gvec_fscale_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32) + #ifndef CONFIG_USER_ONLY DEF_HELPER_2(exception_return, void, env, i64) #endif diff --git a/target/arm/tcg/sve_helper.c b/target/arm/tcg/sve_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/sve_helper.c +++ b/target/arm/tcg/sve_helper.c @@ -XXX,XX +XXX,XX @@ DO_ZPZZ_FP(sve_ah_fabd_h, uint16_t, H1_2, ah_abd_h) DO_ZPZZ_FP(sve_ah_fabd_s, uint32_t, H1_4, ah_abd_s) DO_ZPZZ_FP(sve_ah_fabd_d, uint64_t, H1_8, ah_abd_d) -static inline float64 scalbn_d(float64 a, int64_t b, float_status *s) -{ - int b_int = MIN(MAX(b, INT_MIN), INT_MAX); - return float64_scalbn(a, b_int, s); -} - DO_ZPZZ_FP(sve_fscalbn_h, int16_t, H1_2, float16_scalbn) DO_ZPZZ_FP(sve_fscalbn_s, int32_t, H1_4, float32_scalbn) DO_ZPZZ_FP(sve_fscalbn_d, int64_t, H1_8, scalbn_d) diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-a64.c +++ b/target/arm/tcg/translate-a64.c @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3_ptr * const f_vector_famin[3] = { }; TRANS_FEAT(FAMIN, aa64_faminmax, do_fp3_vector, a, 0, f_vector_famin) +static gen_helper_gvec_3_ptr * const f_vector_fscale[3] = { + gen_helper_gvec_fscale_h, + gen_helper_gvec_fscale_s, + gen_helper_gvec_fscale_d, +}; +TRANS_FEAT(FSCALE, aa64_f8cvt, do_fp3_vector, a, 0, f_vector_fscale) + static bool do_fmlal(DisasContext *s, arg_qrrr_e *a, bool is_s, bool is_2) { if (fp_access_check(s)) { diff --git a/target/arm/tcg/vec_helper64.c b/target/arm/tcg/vec_helper64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/vec_helper64.c +++ b/target/arm/tcg/vec_helper64.c @@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_famax_s, float32_famax, float32) DO_3OP(gvec_famin_s, float32_famin, float32) DO_3OP(gvec_famax_d, float64_famax, float64) DO_3OP(gvec_famin_d, float64_famin, float64) + +DO_3OP(gvec_fscale_h, float16_scalbn, int16_t) +DO_3OP(gvec_fscale_s, float32_scalbn, int32_t) +DO_3OP(gvec_fscale_d, scalbn_d, int64_t) diff --git a/target/arm/tcg/vec_internal.h b/target/arm/tcg/vec_internal.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/vec_internal.h +++ b/target/arm/tcg/vec_internal.h @@ -XXX,XX +XXX,XX @@ float32 float32_famin(float32, float32, float_status *); float64 float64_famax(float64, float64, float_status *); float64 float64_famin(float64, float64, float_status *); +static inline float64 scalbn_d(float64 a, int64_t b, float_status *s) +{ + int b_int = MIN(MAX(b, INT_MIN), INT_MAX); + return float64_scalbn(a, b_int, s); +} + /* * Decode helper functions for predicate as counter. */ -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-22-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpu-features.h | 5 +++++ target/arm/tcg/sme.decode | 6 ++++++ target/arm/tcg/translate-sme.c | 15 +++++++++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_sme2_faminmax(const ARMISARegisters *id) return isar_feature_aa64_sme2(id) && isar_feature_aa64_faminmax(id); } +static inline bool isar_feature_aa64_sme2_f8cvt(const ARMISARegisters *id) +{ + return isar_feature_aa64_sme2(id) && isar_feature_aa64_f8cvt(id); +} + static inline bool isar_feature_aa64_sve_i8mm(const ARMISARegisters *id) { return isar_feature_aa64_sve(id) && isar_feature_aa64_sme_sve_i8mm(id); diff --git a/target/arm/tcg/sme.decode b/target/arm/tcg/sme.decode index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/sme.decode +++ b/target/arm/tcg/sme.decode @@ -XXX,XX +XXX,XX @@ ADD_n1 1100000 1 .. 10 .... 1010.0 11000 .... 0 @z2z_4x1 SQDMULH_n1 1100000 1 .. 10 .... 1010.1 00000 .... 0 @z2z_2x1 SQDMULH_n1 1100000 1 .. 10 .... 1010.1 00000 .... 0 @z2z_4x1 +FSCALE_n1 1100000 1 .. 10 .... 1010.0 01100 .... 0 @z2z_2x1 +FSCALE_n1 1100000 1 .. 10 .... 1010.0 01100 .... 0 @z2z_4x1 + ### SME2 Multi-vector Multiple Vectors SVE Destructive %zm_ax2 17:4 !function=times_2 @@ -XXX,XX +XXX,XX @@ FAMAX_nn 1100000 1 .. 1 ..... 1011.0 01010 .... 0 @z2z_4x4 FAMIN_nn 1100000 1 .. 1 ..... 1011.0 01010 .... 1 @z2z_2x2 FAMIN_nn 1100000 1 .. 1 ..... 1011.0 01010 .... 1 @z2z_4x4 +FSCALE_nn 1100000 1 .. 1 ..... 1011.0 01100 .... 0 @z2z_2x2 +FSCALE_nn 1100000 1 .. 1 ..... 1011.0 01100 .... 0 @z2z_4x4 + ### SME2 Multi-vector Multiple and Single Array Vectors &azz_n n off rv zn zm diff --git a/target/arm/tcg/translate-sme.c b/target/arm/tcg/translate-sme.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-sme.c +++ b/target/arm/tcg/translate-sme.c @@ -XXX,XX +XXX,XX @@ static bool do_z2z_n1_fpst(DisasContext *s, arg_z2z_en *a, { int esz = a->esz, n, dn, vsz, mofs; bool overlap = false; - gen_helper_gvec_3_ptr *fn; + gen_helper_gvec_3_ptr *fn = fns[esz]; TCGv_ptr fpst; + if (fn == NULL) { + return false; + } /* These insns use MO_8 to encode BFloat16. */ if (esz == MO_8 && !dc_isar_feature(aa64_sme_b16b16, s)) { return false; @@ -XXX,XX +XXX,XX @@ static bool do_z2z_n1_fpst(DisasContext *s, arg_z2z_en *a, } fpst = fpstatus_ptr(esz == MO_16 ? FPST_A64_F16 : FPST_A64); - fn = fns[esz]; n = a->n; dn = a->zdn; mofs = vec_full_reg_offset(s, a->zm); @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3_ptr * const f_vector_famin[4] = { }; TRANS_FEAT(FAMIN_nn, aa64_sme2_faminmax, do_z2z_nn_fpst, a, f_vector_famin) +static gen_helper_gvec_3_ptr * const f_vector_fscale[4] = { + NULL, + gen_helper_gvec_fscale_h, + gen_helper_gvec_fscale_s, + gen_helper_gvec_fscale_d, +}; +TRANS_FEAT(FSCALE_n1, aa64_sme2_f8cvt, do_z2z_n1_fpst, a, f_vector_fscale) +TRANS_FEAT(FSCALE_nn, aa64_sme2_f8cvt, do_z2z_nn_fpst, a, f_vector_fscale) + /* Add/Sub vector Z[m] to each Z[n*N] with result in ZA[d*N]. */ static bool do_azz_n1(DisasContext *s, arg_azz_n *a, int esz, GVecGen3FnVar *fn) -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> We want to be able to reference ARMVectorType etc from common code, so move it out of cpu.h. Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-23-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpu.h | 38 +--------------------------------- target/arm/vector-type.h | 44 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 37 deletions(-) create mode 100644 target/arm/vector-type.h 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 @@ #include "target/arm/cpu-sysregs.h" #include "target/arm/mmuidx.h" #include "hw/intc/arm_gicv5_types.h" +#include "target/arm/vector-type.h" #define EXCP_UDEF 1 /* undefined instruction */ #define EXCP_SWI 2 /* software interrupt */ @@ -XXX,XX +XXX,XX @@ typedef struct ARMGenericTimer { uint64_t ctl; /* Timer Control register */ } ARMGenericTimer; -/* Define a maximum sized vector register. - * For 32-bit, this is a 128-bit NEON/AdvSIMD register. - * For 64-bit, this is a 2048-bit SVE register. - * - * Note that the mapping between S, D, and Q views of the register bank - * differs between AArch64 and AArch32. - * In AArch32: - * Qn = regs[n].d[1]:regs[n].d[0] - * Dn = regs[n / 2].d[n & 1] - * Sn = regs[n / 4].d[n % 4 / 2], - * bits 31..0 for even n, and bits 63..32 for odd n - * (and regs[16] to regs[31] are inaccessible) - * In AArch64: - * Zn = regs[n].d[*] - * Qn = regs[n].d[1]:regs[n].d[0] - * Dn = regs[n].d[0] - * Sn = regs[n].d[0] bits 31..0 - * Hn = regs[n].d[0] bits 15..0 - * - * This corresponds to the architecturally defined mapping between - * the two execution states, and means we do not need to explicitly - * map these registers when changing states. - * - * Align the data for use with TCG host vector operations. - */ - -#define ARM_MAX_VQ 16 - -typedef struct ARMVectorReg { - uint64_t d[2 * ARM_MAX_VQ] QEMU_ALIGNED(16); -} ARMVectorReg; - -/* In AArch32 mode, predicate registers do not exist at all. */ -typedef struct ARMPredicateReg { - uint64_t p[DIV_ROUND_UP(2 * ARM_MAX_VQ, 8)] QEMU_ALIGNED(16); -} ARMPredicateReg; - /* In AArch32 mode, PAC keys do not exist at all. */ typedef struct ARMPACKey { uint64_t lo, hi; diff --git a/target/arm/vector-type.h b/target/arm/vector-type.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/target/arm/vector-type.h @@ -XXX,XX +XXX,XX @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef TARGET_ARM_VECTOR_TYPE_H +#define TARGET_ARM_VECTOR_TYPE_H + +/* + * Define a maximum sized vector register. + * For 32-bit, this is a 128-bit NEON/AdvSIMD register. + * For 64-bit, this is a 2048-bit SVE register. + * + * Note that the mapping between S, D, and Q views of the register bank + * differs between AArch64 and AArch32. + * In AArch32: + * Qn = regs[n].d[1]:regs[n].d[0] + * Dn = regs[n / 2].d[n & 1] + * Sn = regs[n / 4].d[n % 4 / 2], + * bits 31..0 for even n, and bits 63..32 for odd n + * (and regs[16] to regs[31] are inaccessible) + * In AArch64: + * Zn = regs[n].d[*] + * Qn = regs[n].d[1]:regs[n].d[0] + * Dn = regs[n].d[0] + * Sn = regs[n].d[0] bits 31..0 + * Hn = regs[n].d[0] bits 15..0 + * + * This corresponds to the architecturally defined mapping between + * the two execution states, and means we do not need to explicitly + * map these registers when changing states. + * + * Align the data for use with TCG host vector operations. + */ + +#define ARM_MAX_VQ 16 + +typedef struct ARMVectorReg { + uint64_t d[2 * ARM_MAX_VQ] QEMU_ALIGNED(16); +} ARMVectorReg; + +/* In AArch32 mode, predicate registers do not exist at all. */ +typedef struct ARMPredicateReg { + uint64_t p[DIV_ROUND_UP(2 * ARM_MAX_VQ, 8)] QEMU_ALIGNED(16); +} ARMPredicateReg; + +#endif -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> We will shortly need this outside of sme_helper.c. Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-24-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/tcg/sme_helper.c | 6 ------ target/arm/tcg/vec_internal.h | 8 ++++++++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/target/arm/tcg/sme_helper.c b/target/arm/tcg/sme_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/sme_helper.c +++ b/target/arm/tcg/sme_helper.c @@ -XXX,XX +XXX,XX @@ #define HELPER_H "tcg/helper-sme-defs.h" #include "exec/helper-info.c.inc" -static bool vectors_overlap(ARMVectorReg *x, unsigned nx, - ARMVectorReg *y, unsigned ny) -{ - return !(x + nx <= y || y + ny <= x); -} - void helper_set_svcr(CPUARMState *env, uint32_t val, uint32_t mask) { aarch64_set_svcr(env, val, mask); diff --git a/target/arm/tcg/vec_internal.h b/target/arm/tcg/vec_internal.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/vec_internal.h +++ b/target/arm/tcg/vec_internal.h @@ -XXX,XX +XXX,XX @@ #define TARGET_ARM_VEC_INTERNAL_H #include "fpu/softfloat.h" +#include "vector-type.h" typedef struct CPUArchState CPUARMState; @@ -XXX,XX +XXX,XX @@ static inline void depositn(uint64_t *p, unsigned pos, } } +/* Determine if [x, x+nx) overlaps [y, y+ny). */ +static inline bool vectors_overlap(ARMVectorReg *x, unsigned nx, + ARMVectorReg *y, unsigned ny) +{ + return !(x + nx <= y || y + ny <= x); +} + #define DO_3OP(NAME, FUNC, TYPE) \ void HELPER(NAME)(void *vd, void *vn, void *vm, \ float_status * stat, uint32_t desc) \ -- 2.43.0
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