:p
atchew
Login
Hi; here's an arm pullreq. These are all bugfixes and minor docs updates. thanks -- PMM The following changes since commit 499039798cdad7d86b787fec0eaf1da4151c0f05: Merge tag 'pull-request-2026-07-12' of https://gitlab.com/huth/qemu into staging (2026-07-12 21:49:04 +0200) are available in the Git repository at: https://gitlab.com/pm215/qemu.git tags/pull-target-arm-20260713 for you to fetch changes up to 3c2749443429a2a6b60bfa5c32964628631dfa23: hw/misc/stm32_rcc: Correct offset-to-irq calculation (2026-07-13 12:34:17 +0100) ---------------------------------------------------------------- target-arm queue: * hw/misc/zynq_slcr.c: drop duplicate reset value for DDRIOB_DCI_CTRL * hw/arm/tegra241-cmdqv: Do not sync GERRORN on VCMDQ allocation * hw/arm/smmuv3: Sanitize fields provided by guest * hw/i2c: pmbus: clear output buffer on write * docs/system/arm: Add some missing FEAT_FOO we already implement * arm/virt: fix smmuv3_devices leak * target/arm: Be more defensive for invalid tlbi_aa64_get_range * hw/dma: don't allow weird transfer lengths for bcm2835 * hw/net/vmxnet3: Correct bounds check on tx queue index * hw/usb/dev-wacom: Don't write off end of buffer * hw/display/sm501: Don't let guest write off end of buffer * hw/misc/allwinner-r40-ccu.c: Correct handling of out of range accesses * hw/misc/stm32_rcc: Correct offset-to-irq calculation ---------------------------------------------------------------- Alex Bennée (9): docs/system: declare support for FEAT_EVT2 docs/system: add big and little endian features names docs/system: document FEAT_Secure docs/system: document FEAT_MTE4 docs/system: document FEAT_IVIPT docs/system: fix sorting of FEAT_S2[PIE|FWB] docs/system: add FEAT_S2TGran[4|16|64]K features docs/system: add FEAT_HAF hw/dma: don't allow weird transfer lengths for bcm2835 Corvin Köhne (1): hw/misc/zynq_slcr.c: drop duplicate reset value for DDRIOB_DCI_CTRL Eric Auger (5): hw/arm/smmuv3: Fix off-by-one bug in alignment strtab mask hw/arm/smmuv3: Sanitize SMMU_S_STRTAB_BASE_CFG.SPLIT hw/arm/smmuv3: Fix possible overflow in strtab_base computation hw/arm/smmuv3: Check L1STD.SPAN hw/arm/smmuv3: Enforce alignment of L2Ptr according to the span Marc-André Lureau (1): arm/virt: fix smmuv3_devices leak Peter Maydell (7): hw/net/vmxnet3: Correct bounds check on tx queue index hw/usb/dev-wacom: Don't write off end of buffer hw/display/sm501: Catch bad coordinates for RTL operations hw/display/sm501: Avoid overflow problems in bounds check calculations hw/display/sm501: Don't allow guest to set ram size larger than it is hw/misc/allwinner-r40-ccu.c: Correct handling of out of range accesses hw/misc/stm32_rcc: Correct offset-to-irq calculation Richard Henderson (1): target/arm: Be more defensive for invalid tlbi_aa64_get_range Shameer Kolothum (1): hw/arm/tegra241-cmdqv: Do not sync GERRORN on VCMDQ allocation titusr (1): hw/i2c: pmbus: clear output buffer on write docs/system/arm/emulation.rst | 14 +++++++++- hw/arm/smmuv3-internal.h | 3 ++ hw/arm/smmuv3.c | 32 ++++++++++++++++++---- hw/arm/tegra241-cmdqv.c | 7 ++--- hw/arm/virt.c | 1 + hw/display/sm501.c | 64 +++++++++++++++++++++++++++++++++++++------ hw/dma/bcm2835_dma.c | 17 ++++++++++++ hw/i2c/pmbus_device.c | 10 +++++++ hw/misc/allwinner-r40-ccu.c | 6 ++-- hw/misc/stm32_rcc.c | 31 ++++++++++++++++++--- hw/misc/zynq_slcr.c | 1 - hw/net/vmxnet3.c | 2 +- hw/usb/dev-wacom.c | 4 +++ include/hw/misc/stm32_rcc.h | 6 +++- target/arm/cpu-max.c | 2 +- target/arm/tcg/tlb-insns.c | 2 +- tests/qtest/adm1266-test.c | 10 ++++--- 17 files changed, 176 insertions(+), 36 deletions(-)
From: Corvin Köhne <c.koehne@beckhoff.com> When adding a reset value for DDRIOB_DCI_CTRL in c8ba862dbfdc, we haven't noticed that a reset value already exists. DDRIOB is a 32 bit register, so incrementing it by 12 will access the DDRIOB_DCI_CTRL register. According to the manual [1] the correct reset value is 0x00000020. Additionally, c8ba862dbfdc won't work with a reset value of 0x00000021 because it tries to detect a toggle of the reset bit (bit 0). Therefore, we drop the old reset value and keep the new one introduced in c8ba862dbfdc. [1] https://docs.amd.com/r/en-US/ug585-zynq-7000-SoC-TRM/Register-slcr-DDRIOB_DCI_CTRL Fixes: c8ba862dbfdc ("hw/misc/zynq_slcr: Add logic for DCI configuration") Signed-off-by: Corvin Köhne <c.koehne@beckhoff.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-id: 20260707145407.70287-1-corvin.koehne@gmail.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/misc/zynq_slcr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c index XXXXXXX..XXXXXXX 100644 --- a/hw/misc/zynq_slcr.c +++ b/hw/misc/zynq_slcr.c @@ -XXX,XX +XXX,XX @@ static void zynq_slcr_reset_init(Object *obj, ResetType type) = s->regs[R_DDRIOB + 3] = 0x00000e00; s->regs[R_DDRIOB + 4] = s->regs[R_DDRIOB + 5] = s->regs[R_DDRIOB + 6] = 0x00000e00; - s->regs[R_DDRIOB + 12] = 0x00000021; s->regs[R_DDRIOB_DCI_CTRL] = 0x00000020; } -- 2.43.0
From: Shameer Kolothum <skolothumtho@nvidia.com> When a guest hits a command error, the hardware sets GERROR and the guest acknowledges it by writing GERRORN to match. These registers use toggle semantics, and since GERROR is read-only, both GERROR and GERRORN may remain set after an error has been handled. As long as they stay equal there is no pending error, so a subsequent VM is unaffected. When a new VM starts, QEMU allocates the hardware VCMDQ and flushes its cached GERRORN of zero, while the hardware may still have both GERROR and GERRORN set from an error the previous guest acknowledged. This makes them differ again, so the hardware sees a pending error and stall the VCMDQ, leading to CMD_SYNC timeouts. Do not sync GERRORN when allocating a hardware VCMDQ. Fixes: 1d0f77535417 ("hw/arm/tegra241-cmdqv: Route allocated VCMDQ Page0 accesses to the mmap'd host VINTF page0") Suggested-by: Nicolin Chen <nicolinc@nvidia.com> Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com> Reviewed-by: Nicolin Chen <nicolinc@nvidia.com> Tested-by: Nicolin Chen <nicolinc@nvidia.com> Reviewed-by: Eric Auger <eric.auger@redhat.com> Message-id: 20260707112450.111178-1-skolothumtho@nvidia.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/arm/tegra241-cmdqv.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/hw/arm/tegra241-cmdqv.c b/hw/arm/tegra241-cmdqv.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/tegra241-cmdqv.c +++ b/hw/arm/tegra241-cmdqv.c @@ -XXX,XX +XXX,XX @@ static inline uint32_t *tegra241_cmdqv_vintf_lvcmdq_ptr(Tegra241CMDQV *cmdqv, /* * Flush cached register writes into the mmap'd host VINTF page0 after a * successful HW_QUEUE_ALLOC, so the guest's earlier writes survive - * the cache-to-hardware transition. + * the cache-to-hardware transition. GERRORN is intentionally not synced, + * as overwriting it with the cached value could recreate a GERROR != GERRORN + * mismatch and stall the VCMDQ. */ static void tegra241_cmdqv_sync_vcmdq(Tegra241CMDQV *cmdqv, int index) { @@ -XXX,XX +XXX,XX @@ static void tegra241_cmdqv_sync_vcmdq(Tegra241CMDQV *cmdqv, int index) ptr = tegra241_cmdqv_vintf_lvcmdq_ptr(cmdqv, index, A_VCMDQ0_CONFIG); *ptr = cmdqv->vcmdq_config[index]; - - ptr = tegra241_cmdqv_vintf_lvcmdq_ptr(cmdqv, index, A_VCMDQ0_GERRORN); - *ptr = cmdqv->vcmdq_gerrorn[index]; } /* -- 2.43.0
From: Eric Auger <eric.auger@redhat.com> The stream table base address needs to be aligned to its size. With FMT == 0 (linear stream table), the table size is log2size * STE_SIZE (2^6). So the spec says the base address must have ADDR[LOG2SIZE + 5:0] = 0. With FMT == 1 (2 level stream table), the table size is (log2size - split) * L1STD_SIZE (2^3) So the spec days the effective base address is aligned by the SMMU to the larger of 64 bytes or the first-level table size: ADDR[MAX(5, (LOG2SIZE - SPLIT - 1 + 3)):0] = 0. MAKE_64BIT_MASK() second argument is a size and not a shift, so fix this off-by-one computation. Subsequent patches will fix the risk of overflow in MAKE_64BIT_MASK() Signed-off-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Shameer Kolothum <skolothumtho@nvidia.com> Message-id: 20260707085028.165557-2-eric.auger@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/arm/smmuv3-internal.h | 3 +++ hw/arm/smmuv3.c | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -XXX,XX +XXX,XX @@ void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event); void smmuv3_propagate_event(SMMUv3State *s, Evt *evt); int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, SMMUEventInfo *event); +#define STE_SIZE 6 +#define L1STD_SIZE 3 + static inline int oas2bits(int oas_field) { switch (oas_field) { diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -XXX,XX +XXX,XX @@ int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, SMMUEventInfo *event) { dma_addr_t addr, strtab_base; uint32_t log2size; - int strtab_size_shift; + int strtab_size; int ret; trace_smmuv3_find_ste(sid, s->features, s->sid_split); @@ -XXX,XX +XXX,XX @@ int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, SMMUEventInfo *event) * Align strtab base address to table size. For this purpose, assume it * is not bounded by SMMU_IDR1_SIDSIZE. */ - strtab_size_shift = MAX(5, (int)log2size - s->sid_split - 1 + 3); + strtab_size = MAX(6, (int)log2size - s->sid_split + L1STD_SIZE); strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK & - ~MAKE_64BIT_MASK(0, strtab_size_shift); + ~MAKE_64BIT_MASK(0, strtab_size); l1_ste_offset = sid >> s->sid_split; l2_ste_offset = sid & ((1 << s->sid_split) - 1); l1ptr = (dma_addr_t)(strtab_base + l1_ste_offset * sizeof(l1std)); @@ -XXX,XX +XXX,XX @@ int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, SMMUEventInfo *event) } addr = l2ptr + l2_ste_offset * sizeof(*ste); } else { - strtab_size_shift = log2size + 5; + strtab_size = log2size + STE_SIZE; strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK & - ~MAKE_64BIT_MASK(0, strtab_size_shift); + ~MAKE_64BIT_MASK(0, strtab_size); addr = strtab_base + sid * sizeof(*ste); } -- 2.43.0
From: Eric Auger <eric.auger@redhat.com> Currently the guest value for the SPLIT field is not checked. Also the spec says that values different from 6, 8, 10, respectively meaning 4KB, 16kB and 64kB leaf tables are reserved and behave as 6. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3632 Signed-off-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Shameer Kolothum <skolothumtho@nvidia.com> Message-id: 20260707085028.165557-3-eric.auger@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/arm/smmuv3.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -XXX,XX +XXX,XX @@ static MemTxResult smmu_writel(SMMUv3State *s, hwaddr offset, s->strtab_base_cfg = data; if (FIELD_EX32(data, STRTAB_BASE_CFG, FMT) == 1) { s->sid_split = FIELD_EX32(data, STRTAB_BASE_CFG, SPLIT); + if (s->sid_split != 6 && s->sid_split != 8 && s->sid_split != 10) { + /* Other values are reserved, behave as 6 */ + qemu_log_mask(LOG_GUEST_ERROR, + "Invalid STRTAB_BASE_CFG.SPLIT=%u, use 6 instead\n", + s->sid_split); + s->sid_split = 6; + } s->features |= SMMU_FEATURE_2LVL_STE; } break; -- 2.43.0
From: Eric Auger <eric.auger@redhat.com> In the linear stream table mode (FMT = 0), if the guest programs SMMU_STRTAB_BASE_CFG.LOG2SIZE (8 bits) to something bigger than 58, MAKE_64BIT_MASK() will overflow. So cap the mask length to 64. We still comply with the spec ADDR alignment computation: ADDR[LOG2SIZE + 5:0] = 0. In the 2 level stream table mode (FMT = 1), we don't have this risk anymore since SPLIT is sanitized and equals to 6 at minimum. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3632 Signed-off-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Shameer Kolothum <skolothumtho@nvidia.com> Message-id: 20260707085028.165557-4-eric.auger@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/arm/smmuv3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -XXX,XX +XXX,XX @@ int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, SMMUEventInfo *event) addr = l2ptr + l2_ste_offset * sizeof(*ste); } else { strtab_size = log2size + STE_SIZE; + strtab_size = MIN(64, strtab_size); strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK & ~MAKE_64BIT_MASK(0, strtab_size); addr = strtab_base + sid * sizeof(*ste); -- 2.43.0
From: Eric Auger <eric.auger@redhat.com> Span values above 11 are reserved and behave as 0. Also span must be within the range of 0 to (SMMU_STRTAB_BASE_CFG.SPLIT + 1), ie. it must stay within the bounds of the stream table split point. Signed-off-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Shameer Kolothum <skolothumtho@nvidia.com> Message-id: 20260707085028.165557-5-eric.auger@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/arm/smmuv3.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -XXX,XX +XXX,XX @@ int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, SMMUEventInfo *event) span = L1STD_SPAN(&l1std); - if (!span) { + if (!span || span > 11) { /* l2ptr is not valid */ if (!event->inval_ste_allowed) { qemu_log_mask(LOG_GUEST_ERROR, @@ -XXX,XX +XXX,XX @@ int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, SMMUEventInfo *event) event->type = SMMU_EVT_C_BAD_STREAMID; return -EINVAL; } + + if (span > s->sid_split + 1) { + if (!event->inval_ste_allowed) { + qemu_log_mask(LOG_GUEST_ERROR, + "invalid span (0x%x)\n", span); + } + event->type = SMMU_EVT_C_BAD_STREAMID; + return -EINVAL; + } + max_l2_ste = (1 << span) - 1; l2ptr = l1std_l2ptr(&l1std); trace_smmuv3_find_ste_2lvl(s->strtab_base, l1ptr, l1_ste_offset, -- 2.43.0
From: Eric Auger <eric.auger@redhat.com> Spec says: Bits L2Ptr[N:0] are treated as 0 by the SMMU, where N == 5 + (Span - 1). Let's enforce this alignment. Signed-off-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Shameer Kolothum <skolothumtho@nvidia.com> Message-id: 20260707085028.165557-6-eric.auger@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/arm/smmuv3.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -XXX,XX +XXX,XX @@ int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, SMMUEventInfo *event) max_l2_ste = (1 << span) - 1; l2ptr = l1std_l2ptr(&l1std); + + l2ptr &= ~MAKE_64BIT_MASK(0, 6 + (span - 1)); trace_smmuv3_find_ste_2lvl(s->strtab_base, l1ptr, l1_ste_offset, l2ptr, l2_ste_offset, max_l2_ste); if (l2_ste_offset > max_l2_ste) { -- 2.43.0
From: titusr <titusr@google.com> Generally we expect a PMBus sensor to issue writes after all pending reads have completed. If a data read needs to be resumed, this state can be tracked in the device model and the pending data placed in the output buffer. Signed-off-by: Titus Rwantare <titusr@google.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Message-id: 20260706230056.1888992-4-titusr@google.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/i2c/pmbus_device.c | 10 ++++++++++ tests/qtest/adm1266-test.c | 10 ++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/hw/i2c/pmbus_device.c b/hw/i2c/pmbus_device.c index XXXXXXX..XXXXXXX 100644 --- a/hw/i2c/pmbus_device.c +++ b/hw/i2c/pmbus_device.c @@ -XXX,XX +XXX,XX @@ static int pmbus_write_data(SMBusDevice *smd, uint8_t *buf, uint8_t len) pmdev->in_buf_len = len; pmdev->in_buf = buf; + /* clear the output buffer on any new write transaction */ + if (pmdev->out_buf_len != 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: previous read was not completed, %d bytes dropped\n", + __func__, pmdev->out_buf_len); + + pmdev->out_buf_len = 0; + memset(pmdev->out_buf, 0, sizeof(pmdev->out_buf)); + } + pmdev->code = buf[0]; /* PMBus command code */ if (pmdev->code == PMBUS_CLEAR_FAULTS) { diff --git a/tests/qtest/adm1266-test.c b/tests/qtest/adm1266-test.c index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/adm1266-test.c +++ b/tests/qtest/adm1266-test.c @@ -XXX,XX +XXX,XX @@ static void compare_string(QI2CDevice *i2cdev, uint8_t reg, const char *test_str) { - uint8_t len = i2c_get8(i2cdev, reg); - char i2c_str[SMBUS_DATA_MAX_LEN] = {0}; + uint8_t expected_len = strlen(test_str); + uint8_t resp[SMBUS_DATA_MAX_LEN] = {0}; - i2c_read_block(i2cdev, reg, (uint8_t *)i2c_str, len); - g_assert_cmpstr(i2c_str, ==, test_str); + g_assert(expected_len + 1 < SMBUS_DATA_MAX_LEN); + i2c_read_block(i2cdev, reg, resp, expected_len + 1); + g_assert_cmpint(resp[0], ==, expected_len); + g_assert_cmpstr((char *)resp + 1, ==, test_str); } static void write_and_compare_string(QI2CDevice *i2cdev, uint8_t reg, -- 2.43.0
From: Alex Bennée <alex.bennee@linaro.org> The actual implementation supports the additional trapping registers of HCR_TTLBIS | HCR_TTLBOS. We already set the value to 2 for -cpu max and don't currently model any CPUs that only have FEAT_EVT. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260708145841.3032079-2-alex.bennee@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- docs/system/arm/emulation.rst | 1 + target/arm/cpu-max.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) 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_EPAC (Enhanced pointer authentication) - FEAT_ETS2 (Enhanced Translation Synchronization) - FEAT_EVT (Enhanced Virtualization Traps) +- FEAT_EVT2 (Enhanced Virtualization Traps 2) - FEAT_F8F16MM (8-bit floating-point matrix multiply-accumulate to half-precision) - FEAT_F8F32MM (8-bit floating-point matrix multiply-accumulate to single-precision) - FEAT_F32MM (Single-precision Matrix Multiplication) diff --git a/target/arm/cpu-max.c b/target/arm/cpu-max.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu-max.c +++ b/target/arm/cpu-max.c @@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu) t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */ t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* FEAT_TTCNP */ t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* FEAT_XNX */ - t = FIELD_DP32(t, ID_MMFR4, EVT, 2); /* FEAT_EVT */ + t = FIELD_DP32(t, ID_MMFR4, EVT, 2); /* FEAT_EVT2 */ SET_IDREG(isar, ID_MMFR4, t); FIELD_DP32_IDREG(isar, ID_MMFR5, ETS, 2); /* FEAT_ETS2 */ -- 2.43.0
From: Alex Bennée <alex.bennee@linaro.org> We've always supported these features but they have official feature names in the Arm ARM now so we should declare them for completeness. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260708145841.3032079-3-alex.bennee@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- docs/system/arm/emulation.rst | 4 ++++ 1 file changed, 4 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_BBML1 (Translation table break-before-make level 1) - FEAT_BBML2 (Translation table break-before-make level 2) - FEAT_BF16 (AArch64 BFloat16 instructions) +- FEAT_BigEnd (Support for big-endian at EL1 and above) +- FEAT_BigEndEL0 (Support for big-endian at EL0) - FEAT_BTI (Branch Target Identification) - FEAT_CCIDX (Extended cache index) - FEAT_CHK (Check Feature Status) @@ -XXX,XX +XXX,XX @@ the following architecture extensions: - FEAT_IDST (ID space trap handling) - FEAT_IESB (Implicit error synchronization event) - FEAT_JSCVT (JavaScript conversion instructions) +- FEAT_LittleEnd (Support for little-endian at EL1 and above) +- FEAT_LittleEndEL0 (Support for little-endian at EL0) - FEAT_LOR (Limited ordering regions) - FEAT_LPA (Large Physical Address space) - FEAT_LPA2 (Large Physical and virtual Address space v2) -- 2.43.0
From: Alex Bennée <alex.bennee@linaro.org> We have had support for Secure state ever since the initial TrustZone support. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260708145841.3032079-4-alex.bennee@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- docs/system/arm/emulation.rst | 1 + 1 file changed, 1 insertion(+) 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_S2FWB (Stage 2 forced Write-Back) - FEAT_SB (Speculation Barrier) - FEAT_SCTLR2 (Extension to SCTLR_ELx) +- FEAT_Secure (Support for Secure state) - FEAT_SEL2 (Secure EL2) - FEAT_SHA1 (SHA1 instructions) - FEAT_SHA256 (SHA256 instructions) -- 2.43.0
From: Alex Bennée <alex.bennee@linaro.org> FEAT_MTE4 includes the sub-features: FEAT_MTE_CANONICAL_TAGS, FEAT_MTE_TAGGED_FAR, FEAT_MTE_STORE_ONLY and FEAT_MTE_NO_ADDRESS_TAGS. We have already implemented those so update the docs to include the rolled up feature. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260708145841.3032079-5-alex.bennee@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- docs/system/arm/emulation.rst | 1 + 1 file changed, 1 insertion(+) 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_MTE (Memory Tagging Extension) - FEAT_MTE2 (Memory Tagging Extension) - FEAT_MTE3 (MTE Asymmetric Fault Handling) +- FEAT_MTE4 (Enhanced Memory Tagging Extension) - FEAT_MTE_ASYM_FAULT (Memory tagging asymmetric faults) - FEAT_MTE_ASYNC (Asynchronous reporting of Tag Check Fault) - FEAT_MTE_CANONICAL_TAGS (Canonical tag checking) -- 2.43.0
From: Alex Bennée <alex.bennee@linaro.org> This is for documentation completeness - a system implements FEAT_IVIPT if it implements any permitted instruction cache implementation. QEMU doesn't model caches which is a permitted (non)implementation. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260708145841.3032079-6-alex.bennee@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- docs/system/arm/emulation.rst | 1 + 1 file changed, 1 insertion(+) 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_I8MM (AArch64 Int8 matrix multiplication instructions) - FEAT_IDST (ID space trap handling) - FEAT_IESB (Implicit error synchronization event) +- FEAT_IVIPT (The IVIPT Extension) - FEAT_JSCVT (JavaScript conversion instructions) - FEAT_LittleEnd (Support for little-endian at EL1 and above) - FEAT_LittleEndEL0 (Support for little-endian at EL0) -- 2.43.0
From: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260708145841.3032079-7-alex.bennee@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- docs/system/arm/emulation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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_RNG_TRAP (Trapping support for RNDR/RNDRRS) - FEAT_RPRES (Increased precision of FRECPE and FRSQRTE) - FEAT_S1PIE (Stage 1 permission indirections) -- FEAT_S2PIE (Stage 2 permission indirections) - FEAT_S2FWB (Stage 2 forced Write-Back) +- FEAT_S2PIE (Stage 2 permission indirections) - FEAT_SB (Speculation Barrier) - FEAT_SCTLR2 (Extension to SCTLR_ELx) - FEAT_Secure (Support for Secure state) -- 2.43.0
From: Alex Bennée <alex.bennee@linaro.org> We already have the logic to handle these granule sizes in our stage 2 page table walk code. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260708145841.3032079-8-alex.bennee@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- docs/system/arm/emulation.rst | 3 +++ 1 file changed, 3 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_S1PIE (Stage 1 permission indirections) - FEAT_S2FWB (Stage 2 forced Write-Back) - FEAT_S2PIE (Stage 2 permission indirections) +- FEAT_S2TGran16K (Support for 16KB memory translation granule size at stage 2) +- FEAT_S2TGran4K (Support for 4KB memory translation granule size at stage 2) +- FEAT_S2TGran64K (Support for 64KB memory translation granule size at stage 2) - FEAT_SB (Speculation Barrier) - FEAT_SCTLR2 (Extension to SCTLR_ELx) - FEAT_Secure (Support for Secure state) -- 2.43.0
From: Alex Bennée <alex.bennee@linaro.org> This is a subset of FEAT_HAFDBS which we have already implemented. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260708145841.3032079-9-alex.bennee@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- docs/system/arm/emulation.rst | 1 + 1 file changed, 1 insertion(+) 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_FlagM2 (Enhancements to flag manipulation instructions) - FEAT_GCS (Guarded Control Stack Extension) - FEAT_GTG (Guest translation granule size) +- FEAT_HAF (Hardware management of the Access flag) - FEAT_HAFDBS (Hardware management of the access flag and dirty bit state) - FEAT_HBC (Hinted conditional branches) - FEAT_HCX (Support for the HCRX_EL2 register) -- 2.43.0
From: Marc-André Lureau <marcandre.lureau@redhat.com> Fixes: 92e340997f861 ("hw/arm/virt: Use stored SMMUv3 device list for IORT build") Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-id: 20260709111225.1106856-1-marcandre.lureau@redhat.com Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/arm/virt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -XXX,XX +XXX,XX @@ static void virt_instance_finalize(Object *obj) } g_free(vms->oem_id); g_free(vms->oem_table_id); + g_ptr_array_free(vms->smmuv3_devices, TRUE); } static const TypeInfo virt_machine_info = { -- 2.43.0
From: Richard Henderson <richard.henderson@linaro.org> It's possible to program TCR_ELx with an invalid granule size, which could match passing an invalid granule size to TLBI RVA, which would then fall through to assert in arm_granule_bits. Cc: qemu-stable@nongnu.org Fixes: 3c003f7029e ("target/arm: Use ARMGranuleSize in ARMVAParameters") Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Message-id: 20260710175818.528974-1-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/tcg/tlb-insns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/arm/tcg/tlb-insns.c b/target/arm/tcg/tlb-insns.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/tlb-insns.c +++ b/target/arm/tcg/tlb-insns.c @@ -XXX,XX +XXX,XX @@ static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx, gran = tlbi_range_tg_to_gran_size(page_size_granule); /* The granule encoded in value must match the granule in use. */ - if (gran != param.gran) { + if (gran != param.gran || gran == GranInvalid) { qemu_log_mask(LOG_GUEST_ERROR, "Invalid tlbi page size granule %d\n", page_size_granule); return ret; -- 2.43.0
From: Alex Bennée <alex.bennee@linaro.org> The datasheet doesn't explicitly say that TXFR_LEN has to be word aligned but the fact there is a DMA_D_WIDTH flag to select between 32 bit and 128 bit strongly implies that is how it works. The downstream rpi kernel also goes to efforts to not write sub-4 byte lengths so lets: - fail when mis-programmed and report GUEST_ERROR - catch setting D_WIDTH for 128 bit and report UNIMP Yodel did some digging into the specs (see discussion link): {A} AMBA AXI Protocol Version: 2.0 Specification https://documentation-service.arm.com/static/64256e84314e245d086bc88f {B} BCM2835 ARM Peripherals https://datasheets.raspberrypi.com/bcm2835/bcm2835-peripherals.pdf [1] {A} (p. 10-2) [2] {B} (p. 51) [3] {A} (p. 14-5) [4] {A} (p. 4-3) [5] {A} (p. 9-4) [6] {B} (p. 53) However was unable to come up with an unambiguous conclusion without testing on the real hardware. So in the absence of certainty and for the sake of addressing the DoS I suggest we merge as is for now. Link: https://lore.kernel.org/all/20251111105429.3993300-1-alex.bennee@linaro.org/ Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3201 Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Message-id: 20260710131500.2323848-1-alex.bennee@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> --- hw/dma/bcm2835_dma.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/hw/dma/bcm2835_dma.c b/hw/dma/bcm2835_dma.c index XXXXXXX..XXXXXXX 100644 --- a/hw/dma/bcm2835_dma.c +++ b/hw/dma/bcm2835_dma.c @@ -XXX,XX +XXX,XX @@ static void bcm2835_dma_update(BCM2835DMAState *s, unsigned c) } xlen_td = xlen; + if (ch->ti & BCM2708_DMA_D_WIDTH) { + qemu_log_mask(LOG_UNIMP, "%s: 128bit transfers not yet supported", __func__); + ch->cs |= BCM2708_DMA_ERR; + break; + } + + /* + * Datasheet implies 32bit or 128bit transfers only + * + * TODO: test on real HW and report back. + */ + if (xlen & 0x3) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: bad transfer size\n", __func__); + ch->cs |= BCM2708_DMA_ERR; + break; + } + while (ylen != 0) { /* Normal transfer mode */ while (xlen != 0) { -- 2.43.0
In vmxnet3_io_bar0_write(), we try to bounds-check the TX queue index provided by the guest against the total number of queues. However, we have an off-by-one error: the valid indexes are from 0 to txq_num-1, so we need a "<" comparison, not "<=". Cc: qemu-stable@nongnu.org Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3780 Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Message-id: 20260706175408.905362-1-peter.maydell@linaro.org --- hw/net/vmxnet3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index XXXXXXX..XXXXXXX 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -XXX,XX +XXX,XX @@ vmxnet3_io_bar0_write(void *opaque, hwaddr addr, int tx_queue_idx = VMW_MULTIREG_IDX_BY_ADDR(addr, VMXNET3_REG_TXPROD, VMXNET3_REG_ALIGN); - if (tx_queue_idx <= s->txq_num) { + if (tx_queue_idx < s->txq_num) { vmxnet3_process_tx_queue(s, tx_queue_idx); } else { qemu_log_mask(LOG_GUEST_ERROR, "vmxnet3: Illegal TX queue %d/%d\n", -- 2.43.0
In usb_wacom_handle_data() we allocate a buffer with a size determined by the transfer size requested by the guest. We then fill it in by calling either usb_mouse_poll() or usb_wacom_poll(), both of which functions take a length and return an actual length, which we pass to usb_packet_copy(). However, usb_mouse_poll() doesn't check the buffer size as it fills in the buffer, so if the guest passes an overly short transfer size then it will write off the end of the allocated buffer. Check the length is at least big enough for the minimum 3 byte packet and return nothing if it is not, as usb_wacom_poll() does. Cc: qemu-stable@nongnu.org Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3672 Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Message-id: 20260706182034.1003176-1-peter.maydell@linaro.org --- hw/usb/dev-wacom.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c index XXXXXXX..XXXXXXX 100644 --- a/hw/usb/dev-wacom.c +++ b/hw/usb/dev-wacom.c @@ -XXX,XX +XXX,XX @@ static int usb_mouse_poll(USBWacomState *s, uint8_t *buf, int len) b |= 0x04; } + if (len < 3) { + return 0; + } + buf[0] = b; buf[1] = dx; buf[2] = dy; -- 2.43.0
The sm501 code doesn't check whether a right-to-left operation has specified a width greater than the x-coordinate (which would make it extend off the left edge of the screen), or similarly a height greater than the y-coordinate. This means the guest can misprogram the device so that we underflow when calculating the address of the top left pixel, which might result in accessing out of bounds memory. Catch this as a guest error and ignore the operation. Reported-by: Yannick Wang Tested-by: BALATON Zoltan <balaton@eik.bme.hu> Reviewed-by: BALATON Zoltan <balaton@eik.bme.hu> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20260707150933.1410507-2-peter.maydell@linaro.org Cc: qemu-stable@nongnu.org Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3920 Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/display/sm501.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/display/sm501.c b/hw/display/sm501.c index XXXXXXX..XXXXXXX 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -XXX,XX +XXX,XX @@ static void sm501_2d_operation(SM501State *s) } if (rtl) { + if (dst_x < (width - 1) || dst_y < (height - 1)) { + qemu_log_mask(LOG_GUEST_ERROR, "sm501: RTL op out of bounds\n"); + return; + } dst_x -= width - 1; dst_y -= height - 1; } @@ -XXX,XX +XXX,XX @@ static void sm501_2d_operation(SM501State *s) } if (rtl) { + if (src_x < (width - 1) || src_y < (height - 1)) { + qemu_log_mask(LOG_GUEST_ERROR, "sm501: RTL op out of bounds\n"); + return; + } src_x -= width - 1; src_y -= height - 1; } -- 2.43.0
When we check that a 2D rectangle operation isn't going to run off the end of video RAM, we do the calculations as 32 bit arithmetic. This means that carefully chosen guest register values can cause an overflow so we don't detect that the operation is going to go outside video memory. Abstract the check out into a function, do the calculations as 64-bit arithmetic, and add assertions about the ranges of the inputs. Cc: qemu-stable@nongnu.org Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3584 Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Tested-by: BALATON Zoltan <balaton@eik.bme.hu> Reviewed-by: BALATON Zoltan <balaton@eik.bme.hu> Message-id: 20260707150933.1410507-3-peter.maydell@linaro.org --- hw/display/sm501.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/hw/display/sm501.c b/hw/display/sm501.c index XXXXXXX..XXXXXXX 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -XXX,XX +XXX,XX @@ static inline void hwc_invalidate(SM501State *s, int crt) get_fb_addr(s, crt) + start, end - start); } +static bool sm501_rect_outside_vram(SM501State *s, uint32_t base, + uint32_t x, uint32_t y, + uint32_t width, uint32_t height, + uint32_t pitch, uint32_t bypp) +{ + /* + * Return true if the 2D area specified by the arguments is + * partially or completely outside the VRAM (a guest error) + * + * Limits on the input sizes mean we can't overflow as long as + * we do all the arithmetic at 64 bits. + */ + uint64_t rect_size, last_addr; + + assert(x <= UINT16_MAX && y <= UINT16_MAX && height <= UINT16_MAX && + pitch <= UINT16_MAX && bypp <= 8); + rect_size = (((uint64_t)y + height) * pitch + x + width) * bypp; + last_addr = base + rect_size; + + return last_addr >= get_local_mem_size(s); +} + static void sm501_2d_operation(SM501State *s) { int cmd = (s->twoD_control >> 16) & 0x1F; @@ -XXX,XX +XXX,XX @@ static void sm501_2d_operation(SM501State *s) dst_y -= height - 1; } - if (dst_base >= get_local_mem_size(s) || - dst_base + (dst_x + width + (dst_y + height) * dst_pitch) * bypp >= - get_local_mem_size(s)) { + if (sm501_rect_outside_vram(s, dst_base, dst_x, dst_y, width, height, + dst_pitch, bypp)) { qemu_log_mask(LOG_GUEST_ERROR, "sm501: 2D op dest is outside vram.\n"); return; } @@ -XXX,XX +XXX,XX @@ static void sm501_2d_operation(SM501State *s) src_y -= height - 1; } - if (src_base >= get_local_mem_size(s) || - src_base + (src_x + width + (src_y + height) * src_pitch) * bypp >= - get_local_mem_size(s)) { + if (sm501_rect_outside_vram(s, src_base, src_x, src_y, width, height, + src_pitch, bypp)) { qemu_log_mask(LOG_GUEST_ERROR, "sm501: 2D op src is outside vram.\n"); return; -- 2.43.0
The SM501 DRAM_CONTROL register has a 7 bit Size field which allows the guest to change the local memory size. We use the local memory size in bounds checks calculations for 2D operations. Currently we have no check on the validity of the value the guest programs to this field, which means that the guest can: - set it to a reserved value (6 or 7) which will cause get_local_mem_size() to read outside sm501_mem_local_size[] - set it to a value corresponding to more RAM than the card was created with, so that the 2D bounds check will let 2D operations access off the end of the memory region Fix this by decoupling the value the guest reads and writes to this field from the internal size we consider the local memory to have. We validate changes and ignore them except for readback if they would be reserved values or values for more memory than the card has. Cc: qemu-stable@nongnu.org Reported-by: Heechan Kang Tested-by: BALATON Zoltan <balaton@eik.bme.hu> Reviewed-by: BALATON Zoltan <balaton@eik.bme.hu> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20260707150933.1410507-4-peter.maydell@linaro.org Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3811 Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/display/sm501.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/hw/display/sm501.c b/hw/display/sm501.c index XXXXXXX..XXXXXXX 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -XXX,XX +XXX,XX @@ static uint32_t get_local_mem_size_index(uint32_t size) return index; } +static void set_new_local_mem_size_index(SM501State *s, uint32_t idx) +{ + /* + * Update local_mem_size_index on guest write. We don't allow this + * to be set to larger than the actual RAM size. (The guest will + * still read back the SYSTEM_CONTROL.Size bits that it wrote.) + */ + if (idx < ARRAY_SIZE(sm501_mem_local_size) && + sm501_mem_local_size[idx] <= memory_region_size(&s->local_mem_region)) { + s->local_mem_size_index = idx; + return; + } + qemu_log_mask(LOG_GUEST_ERROR, + "sm501: Guest set DRAM_CONTROL.Size to 0x%x but " + "local memory is not that large\n", + idx); + /* Don't change the effective size, leave it as whatever it was */ +} + static ram_addr_t get_fb_addr(SM501State *s, int crt) { return (crt ? s->dc_crt_fb_addr : s->dc_panel_fb_addr) & 0x3FFFFF0; @@ -XXX,XX +XXX,XX @@ static uint64_t sm501_system_config_read(void *opaque, hwaddr addr, ret = 0x050100A0; break; case SM501_DRAM_CONTROL: - ret = (s->dram_control & 0x07F107C0) | s->local_mem_size_index << 13; + ret = (s->dram_control & 0x07F1E7C0); break; case SM501_ARBTRTN_CONTROL: ret = s->arbitration_control; @@ -XXX,XX +XXX,XX @@ static void sm501_system_config_write(void *opaque, hwaddr addr, s->gpio_63_32_control = value & 0xFF80FFFF; break; case SM501_DRAM_CONTROL: - s->local_mem_size_index = (value >> 13) & 0x7; - /* TODO : check validity of size change */ + set_new_local_mem_size_index(s, (value >> 13) & 0x7); s->dram_control &= 0x80000000; s->dram_control |= value & 0x7FFFFFC3; break; -- 2.43.0
In allwinner_r40_ccu_write() we handle writes to a MemoryRegion of size AW_R40_CCU_IOSIZE, and the register array is sized accordingly at (AW_R40_CCU_IOSIZE / sizeof(uint32_t)). However, one of the cases in the switch is a range up to AW_R40_CCU_IOSIZE, which makes Coverity think we might index off the end of the array. We also have a similar case in the read function, but since that returns early it doesn't have the same issue. Adjust the handling of out of range accesses: - use AW_R40_CCU_IOSIZE - 4 as the upper bound, as this is the largest value we will actually see - return early in the write case, as we do in the read case Coverity CID: 1663687 Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com> Message-id: 20260709104802.1989086-1-peter.maydell@linaro.org --- hw/misc/allwinner-r40-ccu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/misc/allwinner-r40-ccu.c b/hw/misc/allwinner-r40-ccu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/misc/allwinner-r40-ccu.c +++ b/hw/misc/allwinner-r40-ccu.c @@ -XXX,XX +XXX,XX @@ static uint64_t allwinner_r40_ccu_read(void *opaque, hwaddr offset, const uint32_t idx = REG_INDEX(offset); switch (offset) { - case 0x324 ... AW_R40_CCU_IOSIZE: + case 0x324 ... AW_R40_CCU_IOSIZE - 4: qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n", __func__, (uint32_t)offset); return 0; @@ -XXX,XX +XXX,XX @@ static void allwinner_r40_ccu_write(void *opaque, hwaddr offset, val |= REG_PLL_LOCK; } break; - case 0x324 ... AW_R40_CCU_IOSIZE: + case 0x324 ... AW_R40_CCU_IOSIZE - 4: qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n", __func__, (uint32_t)offset); - break; + return; default: qemu_log_mask(LOG_UNIMP, "%s: unimplemented write offset 0x%04x\n", __func__, (uint32_t)offset); -- 2.43.0
In the STM32 RCC, there is a block of 5 "enable" registers, each of which has 32 bits; each bit determines the level of one of the 5 * 32 = 160 enable_irq output lines. The code calculates the irq to be worked on using irq_offset = ((addr - STM32_RCC_AHB1_ENR) / 4) * 32; This assumes that the registers are all consecutive; however, there is a gap between the AHB1/2/3 registers and the APB1/2 registers, so for the APB1/2 registers we calculate a number that is 32 too high and can index off the end of the enable_irq[] array. The handling of the reset registers has an identical bug. Adjust the calculation of irq_offset to cope with the gap, and fix the case labels so accesses to the gap fall into the default LOG_UNIMP rather than being treated as if they were an actual register. Coverity CID: 1663683, 1663686 Cc: qemu-stable@nongnu.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-id: 20260709104832.1989240-1-peter.maydell@linaro.org --- hw/misc/stm32_rcc.c | 31 +++++++++++++++++++++++++++---- include/hw/misc/stm32_rcc.h | 6 +++++- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/hw/misc/stm32_rcc.c b/hw/misc/stm32_rcc.c index XXXXXXX..XXXXXXX 100644 --- a/hw/misc/stm32_rcc.c +++ b/hw/misc/stm32_rcc.c @@ -XXX,XX +XXX,XX @@ static uint64_t stm32_rcc_read(void *opaque, hwaddr addr, unsigned int size) return value; } +static int reg_offset_to_irq_offset(hwaddr addr) +{ + /* + * The reset and enable registers aren't all consecutive. In getting the + * irq index from the register offset, we need to account for the gap + * between the AHB regs and the APB regs. + */ + switch (addr) { + case STM32_RCC_AHB1_RSTR ... STM32_RCC_AHB3_RSTR: + return ((addr - STM32_RCC_AHB1_RSTR) / 4) * 32; + case STM32_RCC_APB1_RSTR ... STM32_RCC_APB2_RSTR: + return ((addr - STM32_RCC_APB1_RSTR) / 4) * 32 + STM32_RCC_N_AHB_IRQS; + case STM32_RCC_AHB1_ENR ... STM32_RCC_AHB3_ENR: + return ((addr - STM32_RCC_AHB1_ENR) / 4) * 32; + case STM32_RCC_APB1_ENR ... STM32_RCC_APB2_ENR: + return ((addr - STM32_RCC_APB1_ENR) / 4) * 32 + STM32_RCC_N_AHB_IRQS; + default: + g_assert_not_reached(); + } +} + static void stm32_rcc_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { @@ -XXX,XX +XXX,XX @@ static void stm32_rcc_write(void *opaque, hwaddr addr, } switch (addr) { - case STM32_RCC_AHB1_RSTR...STM32_RCC_APB2_RSTR: + case STM32_RCC_AHB1_RSTR ... STM32_RCC_AHB3_RSTR: + case STM32_RCC_APB1_RSTR ... STM32_RCC_APB2_RSTR: prev_value = s->regs[addr / 4]; s->regs[addr / 4] = value; - irq_offset = ((addr - STM32_RCC_AHB1_RSTR) / 4) * 32; + irq_offset = reg_offset_to_irq_offset(addr); for (int i = 0; i < 32; i++) { new_value = extract32(value, i, 1); if (extract32(prev_value, i, 1) && !new_value) { @@ -XXX,XX +XXX,XX @@ static void stm32_rcc_write(void *opaque, hwaddr addr, } } return; - case STM32_RCC_AHB1_ENR...STM32_RCC_APB2_ENR: + case STM32_RCC_AHB1_ENR ... STM32_RCC_AHB3_ENR: + case STM32_RCC_APB1_ENR ... STM32_RCC_APB2_ENR: prev_value = s->regs[addr / 4]; s->regs[addr / 4] = value; - irq_offset = ((addr - STM32_RCC_AHB1_ENR) / 4) * 32; + irq_offset = reg_offset_to_irq_offset(addr); for (int i = 0; i < 32; i++) { new_value = extract32(value, i, 1); if (!extract32(prev_value, i, 1) && new_value) { diff --git a/include/hw/misc/stm32_rcc.h b/include/hw/misc/stm32_rcc.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/misc/stm32_rcc.h +++ b/include/hw/misc/stm32_rcc.h @@ -XXX,XX +XXX,XX @@ #define STM32_RCC_NREGS ((STM32_RCC_DCKCFGR2 >> 2) + 1) #define STM32_RCC_PERIPHERAL_SIZE 0x400 -#define STM32_RCC_NIRQS (32 * 5) /* 32 bits per reg, 5 en/rst regs */ + +/* 32 bits per reg, 3 AHB regs and 2 APB regs */ +#define STM32_RCC_N_AHB_IRQS (32 * 3) +#define STM32_RCC_N_APB_IRQS (32 * 2) +#define STM32_RCC_NIRQS (STM32_RCC_N_AHB_IRQS + STM32_RCC_N_APB_IRQS) #define STM32_RCC_GPIO_IRQ_OFFSET 0 -- 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