1
arm pullreq for rc1. All minor bugfixes, except for the sve-default-vector-length
1
Hi; here's a target-arm pullreq to go in before softfreeze.
2
patches, which are somewhere between a bugfix and a new feature.
2
This is actually pretty much entirely bugfixes (since the
3
SEL2 timers we implement here are a missing part of a feature
4
we claim to already implement).
3
5
4
thanks
6
thanks
5
-- PMM
7
-- PMM
6
8
7
The following changes since commit c08ccd1b53f488ac86c1f65cf7623dc91acc249a:
9
The following changes since commit 98c7362b1efe651327385a25874a73e008c6549e:
8
10
9
Merge remote-tracking branch 'remotes/rth-gitlab/tags/pull-tcg-20210726' into staging (2021-07-27 08:35:01 +0100)
11
Merge tag 'accel-cpus-20250306' of https://github.com/philmd/qemu into staging (2025-03-07 07:39:49 +0800)
10
12
11
are available in the Git repository at:
13
are available in the Git repository at:
12
14
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210727
15
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20250307
14
16
15
for you to fetch changes up to e229a179a503f2aee43a76888cf12fbdfe8a3749:
17
for you to fetch changes up to 0ce0739d46983e5e88fa9c149cb305689c9d8c6f:
16
18
17
hw: aspeed_gpio: Fix memory size (2021-07-27 11:00:00 +0100)
19
target/rx: Remove TCG_CALL_NO_WG from helpers which write env (2025-03-07 15:03:20 +0000)
18
20
19
----------------------------------------------------------------
21
----------------------------------------------------------------
20
target-arm queue:
22
target-arm queue:
21
* hw/arm/smmuv3: Check 31st bit to see if CD is valid
23
* hw/arm/smmu-common: Remove the repeated ttb field
22
* qemu-options.hx: Fix formatting of -machine memory-backend option
24
* hw/gpio: npcm7xx: fixup out-of-bounds access
23
* hw: aspeed_gpio: Fix memory size
25
* tests/functional/test_arm_sx1: Check whether the serial console is working
24
* hw/arm/nseries: Display hexadecimal value with '0x' prefix
26
* target/arm: Fix minor bugs in generic timer register handling
25
* Add sve-default-vector-length cpu property
27
* target/arm: Implement SEL2 physical and virtual timers
26
* docs: Update path that mentions deprecated.rst
28
* target/arm: Correct STRD, LDRD atomicity and fault behaviour
27
* hw/intc/armv7m_nvic: for v8.1M VECTPENDING hides S exceptions from NS
29
* target/arm: Make dummy debug registers RAZ, not NOP
28
* hw/intc/armv7m_nvic: Correct size of ICSR.VECTPENDING
30
* util/qemu-timer.c: Don't warp timer from timerlist_rearm()
29
* hw/intc/armv7m_nvic: ISCR.ISRPENDING is set for non-enabled pending interrupts
31
* include/exec/memop.h: Expand comment for MO_ATOM_SUBALIGN
30
* target/arm: Report M-profile alignment faults correctly to the guest
32
* hw/arm/smmu: Introduce smmu_configs_inv_sid_range() helper
31
* target/arm: Add missing 'return's after calling v7m_exception_taken()
33
* target/rx: Set exception vector base to 0xffffff80
32
* target/arm: Enforce that M-profile SP low 2 bits are always zero
34
* target/rx: Remove TCG_CALL_NO_WG from helpers which write env
33
35
34
----------------------------------------------------------------
36
----------------------------------------------------------------
35
Joe Komlodi (1):
37
Alex Bennée (4):
36
hw/arm/smmuv3: Check 31st bit to see if CD is valid
38
target/arm: Implement SEL2 physical and virtual timers
39
target/arm: Document the architectural names of our GTIMERs
40
hw/arm: enable secure EL2 timers for virt machine
41
hw/arm: enable secure EL2 timers for sbsa machine
37
42
38
Joel Stanley (1):
43
JianChunfu (2):
39
hw: aspeed_gpio: Fix memory size
44
hw/arm/smmu-common: Remove the repeated ttb field
45
hw/arm/smmu: Introduce smmu_configs_inv_sid_range() helper
40
46
41
Mao Zhongyi (1):
47
Keith Packard (2):
42
docs: Update path that mentions deprecated.rst
48
target/rx: Set exception vector base to 0xffffff80
49
target/rx: Remove TCG_CALL_NO_WG from helpers which write env
43
50
44
Peter Maydell (7):
51
Patrick Venture (1):
45
qemu-options.hx: Fix formatting of -machine memory-backend option
52
hw/gpio: npcm7xx: fixup out-of-bounds access
46
target/arm: Enforce that M-profile SP low 2 bits are always zero
47
target/arm: Add missing 'return's after calling v7m_exception_taken()
48
target/arm: Report M-profile alignment faults correctly to the guest
49
hw/intc/armv7m_nvic: ISCR.ISRPENDING is set for non-enabled pending interrupts
50
hw/intc/armv7m_nvic: Correct size of ICSR.VECTPENDING
51
hw/intc/armv7m_nvic: for v8.1M VECTPENDING hides S exceptions from NS
52
53
53
Philippe Mathieu-Daudé (1):
54
Peter Maydell (11):
54
hw/arm/nseries: Display hexadecimal value with '0x' prefix
55
target/arm: Apply correct timer offset when calculating deadlines
56
target/arm: Don't apply CNTVOFF_EL2 for EL2_VIRT timer
57
target/arm: Make CNTPS_* UNDEF from Secure EL1 when Secure EL2 is enabled
58
target/arm: Always apply CNTVOFF_EL2 for CNTV_TVAL_EL02 accesses
59
target/arm: Refactor handling of timer offset for direct register accesses
60
target/arm: Correct LDRD atomicity and fault behaviour
61
target/arm: Correct STRD atomicity
62
target/arm: Drop unused address_offset from op_addr_{rr, ri}_post()
63
target/arm: Make dummy debug registers RAZ, not NOP
64
util/qemu-timer.c: Don't warp timer from timerlist_rearm()
65
include/exec/memop.h: Expand comment for MO_ATOM_SUBALIGN
55
66
56
Richard Henderson (3):
67
Thomas Huth (1):
57
target/arm: Correctly bound length in sve_zcr_get_valid_len
68
tests/functional/test_arm_sx1: Check whether the serial console is working
58
target/arm: Export aarch64_sve_zcr_get_valid_len
59
target/arm: Add sve-default-vector-length cpu property
60
69
61
docs/system/arm/cpu-features.rst | 15 ++++++++++
70
MAINTAINERS | 1 +
62
configure | 2 +-
71
hw/arm/smmu-internal.h | 5 -
63
hw/arm/smmuv3-internal.h | 2 +-
72
include/exec/memop.h | 8 +-
64
target/arm/cpu.h | 5 ++++
73
include/hw/arm/bsa.h | 2 +
65
target/arm/internals.h | 10 +++++++
74
include/hw/arm/smmu-common.h | 7 +-
66
hw/arm/nseries.c | 2 +-
75
target/arm/cpu.h | 2 +
67
hw/gpio/aspeed_gpio.c | 3 +-
76
target/arm/gtimer.h | 14 +-
68
hw/intc/armv7m_nvic.c | 40 +++++++++++++++++++--------
77
target/arm/internals.h | 5 +-
69
target/arm/cpu.c | 14 ++++++++--
78
target/rx/helper.h | 34 ++--
70
target/arm/cpu64.c | 60 ++++++++++++++++++++++++++++++++++++++++
79
hw/arm/sbsa-ref.c | 2 +
71
target/arm/gdbstub.c | 4 +++
80
hw/arm/smmu-common.c | 21 +++
72
target/arm/helper.c | 8 ++++--
81
hw/arm/smmuv3.c | 19 +--
73
target/arm/m_helper.c | 24 ++++++++++++----
82
hw/arm/virt.c | 2 +
74
target/arm/translate.c | 3 ++
83
hw/gpio/npcm7xx_gpio.c | 3 +-
75
target/i386/cpu.c | 2 +-
84
target/arm/cpu.c | 4 +
76
MAINTAINERS | 2 +-
85
target/arm/debug_helper.c | 7 +-
77
qemu-options.hx | 30 +++++++++++---------
86
target/arm/helper.c | 324 ++++++++++++++++++++++++++++++++-------
78
17 files changed, 183 insertions(+), 43 deletions(-)
87
target/arm/tcg/op_helper.c | 8 +-
88
target/arm/tcg/translate.c | 147 +++++++++++-------
89
target/rx/helper.c | 2 +-
90
util/qemu-timer.c | 4 -
91
hw/arm/trace-events | 3 +-
92
tests/functional/test_arm_sx1.py | 7 +-
93
23 files changed, 455 insertions(+), 176 deletions(-)
79
94
diff view generated by jsdifflib
New patch
1
From: JianChunfu <jansef.jian@hj-micro.com>
1
2
3
SMMUTransCfg->ttb is never used in QEMU, TT base address
4
can be accessed by SMMUTransCfg->tt[i]->ttb.
5
6
Signed-off-by: JianChunfu <jansef.jian@hj-micro.com>
7
Reviewed-by: Eric Auger <eric.auger@redhat.com>
8
Message-id: 20250221031034.69822-1-jansef.jian@hj-micro.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/arm/smmu-common.h | 1 -
12
1 file changed, 1 deletion(-)
13
14
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/smmu-common.h
17
+++ b/include/hw/arm/smmu-common.h
18
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUTransCfg {
19
/* Used by stage-1 only. */
20
bool aa64; /* arch64 or aarch32 translation table */
21
bool record_faults; /* record fault events */
22
- uint64_t ttb; /* TT base address */
23
uint8_t oas; /* output address width */
24
uint8_t tbi; /* Top Byte Ignore */
25
int asid;
26
--
27
2.43.0
diff view generated by jsdifflib
1
From: Joel Stanley <joel@jms.id.au>
1
From: Patrick Venture <venture@google.com>
2
2
3
The macro used to calculate the maximum memory size of the MMIO region
3
The reg isn't validated to be a possible register before
4
had a mistake, causing all GPIO models to create a mapping of 0x9D8.
4
it's dereferenced for one case. The mmio space registered
5
The intent was to have it be 0x9D8 - 0x800.
5
for the gpio device is 4KiB but there aren't that many
6
registers in the struct.
6
7
7
This extra size doesn't matter on ast2400 and ast2500, which have a 4KB
8
Cc: qemu-stable@nongnu.org
8
region set aside for the GPIO controller.
9
Fixes: 526dbbe0874 ("hw/gpio: Add GPIO model for Nuvoton NPCM7xx")
9
10
Signed-off-by: Patrick Venture <venture@google.com>
10
On the ast2600 the 3.3V and 1.8V GPIO controllers are 2KB apart, so the
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
regions would overlap. Worse was the 1.8V controller would map over the
12
Message-id: 20250226024603.493148-1-venture@google.com
12
top of the following peripheral, which happens to be the RTC.
13
14
The mmio region used by each device is a maximum of 2KB, so avoid the
15
calculations and hard code this as the maximum.
16
17
Fixes: 36d737ee82b2 ("hw/gpio: Add in AST2600 specific implementation")
18
Signed-off-by: Joel Stanley <joel@jms.id.au>
19
Reviewed-by: Rashmica Gupta <rashmica.g@gmail.com>
20
Reviewed-by: Cédric Le Goater <clg@kaod.org>
21
Message-id: 20210713065854.134634-2-joel@jms.id.au
22
[PMM: fix autocorrect error in commit message]
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
14
---
25
hw/gpio/aspeed_gpio.c | 3 +--
15
hw/gpio/npcm7xx_gpio.c | 3 +--
26
1 file changed, 1 insertion(+), 2 deletions(-)
16
1 file changed, 1 insertion(+), 2 deletions(-)
27
17
28
diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c
18
diff --git a/hw/gpio/npcm7xx_gpio.c b/hw/gpio/npcm7xx_gpio.c
29
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/gpio/aspeed_gpio.c
20
--- a/hw/gpio/npcm7xx_gpio.c
31
+++ b/hw/gpio/aspeed_gpio.c
21
+++ b/hw/gpio/npcm7xx_gpio.c
32
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gpio_regs_write(void *opaque, hwaddr addr, uint64_t v,
33
#define GPIO_1_8V_MEM_SIZE 0x9D8
23
return;
34
#define GPIO_1_8V_REG_ARRAY_SIZE ((GPIO_1_8V_MEM_SIZE - \
35
GPIO_1_8V_REG_OFFSET) >> 2)
36
-#define GPIO_MAX_MEM_SIZE MAX(GPIO_3_6V_MEM_SIZE, GPIO_1_8V_MEM_SIZE)
37
38
static int aspeed_evaluate_irq(GPIOSets *regs, int gpio_prev_high, int gpio)
39
{
40
@@ -XXX,XX +XXX,XX @@ static void aspeed_gpio_realize(DeviceState *dev, Error **errp)
41
}
24
}
42
25
43
memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_gpio_ops, s,
26
- diff = s->regs[reg] ^ value;
44
- TYPE_ASPEED_GPIO, GPIO_MAX_MEM_SIZE);
27
-
45
+ TYPE_ASPEED_GPIO, 0x800);
28
switch (reg) {
46
29
case NPCM7XX_GPIO_TLOCK1:
47
sysbus_init_mmio(sbd, &s->iomem);
30
case NPCM7XX_GPIO_TLOCK2:
48
}
31
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gpio_regs_write(void *opaque, hwaddr addr, uint64_t v,
32
case NPCM7XX_GPIO_PU:
33
case NPCM7XX_GPIO_PD:
34
case NPCM7XX_GPIO_IEM:
35
+ diff = s->regs[reg] ^ value;
36
s->regs[reg] = value;
37
npcm7xx_gpio_update_pins(s, diff);
38
break;
49
--
39
--
50
2.20.1
40
2.43.0
51
41
52
42
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozhongyi@cmss.chinamobile.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
Missed in commit f3478392 "docs: Move deprecation, build
3
The kernel that is used in the sx1 test prints the usual Linux log
4
and license info out of system/"
4
onto the serial console, but this test currently ignores it. To
5
make sure that the serial device is working properly, let's check
6
for some strings in the output here.
5
7
6
Signed-off-by: Mao Zhongyi <maozhongyi@cmss.chinamobile.com>
8
While we're at it, also add the test to the corresponding section
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
in the MAINTAINERS file.
8
Message-id: 20210723065828.1336760-1-maozhongyi@cmss.chinamobile.com
10
11
Signed-off-by: Thomas Huth <thuth@redhat.com>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
13
Message-id: 20250226104833.1176253-1-thuth@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
15
---
11
configure | 2 +-
16
MAINTAINERS | 1 +
12
target/i386/cpu.c | 2 +-
17
tests/functional/test_arm_sx1.py | 7 ++++---
13
MAINTAINERS | 2 +-
18
2 files changed, 5 insertions(+), 3 deletions(-)
14
3 files changed, 3 insertions(+), 3 deletions(-)
15
19
16
diff --git a/configure b/configure
17
index XXXXXXX..XXXXXXX 100755
18
--- a/configure
19
+++ b/configure
20
@@ -XXX,XX +XXX,XX @@ fi
21
22
if test -n "${deprecated_features}"; then
23
echo "Warning, deprecated features enabled."
24
- echo "Please see docs/system/deprecated.rst"
25
+ echo "Please see docs/about/deprecated.rst"
26
echo " features: ${deprecated_features}"
27
fi
28
29
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/i386/cpu.c
32
+++ b/target/i386/cpu.c
33
@@ -XXX,XX +XXX,XX @@ static const X86CPUDefinition builtin_x86_defs[] = {
34
* none", but this is just for compatibility while libvirt isn't
35
* adapted to resolve CPU model versions before creating VMs.
36
* See "Runnability guarantee of CPU models" at
37
- * docs/system/deprecated.rst.
38
+ * docs/about/deprecated.rst.
39
*/
40
X86CPUVersion default_cpu_version = 1;
41
42
diff --git a/MAINTAINERS b/MAINTAINERS
20
diff --git a/MAINTAINERS b/MAINTAINERS
43
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
44
--- a/MAINTAINERS
22
--- a/MAINTAINERS
45
+++ b/MAINTAINERS
23
+++ b/MAINTAINERS
46
@@ -XXX,XX +XXX,XX @@ F: contrib/gitdm/*
24
@@ -XXX,XX +XXX,XX @@ S: Maintained
47
25
F: hw/*/omap*
48
Incompatible changes
26
F: include/hw/arm/omap.h
49
R: libvir-list@redhat.com
27
F: docs/system/arm/sx1.rst
50
-F: docs/system/deprecated.rst
28
+F: tests/functional/test_arm_sx1.py
51
+F: docs/about/deprecated.rst
29
52
30
IPack
53
Build System
31
M: Alberto Garcia <berto@igalia.com>
54
------------
32
diff --git a/tests/functional/test_arm_sx1.py b/tests/functional/test_arm_sx1.py
33
index XXXXXXX..XXXXXXX 100755
34
--- a/tests/functional/test_arm_sx1.py
35
+++ b/tests/functional/test_arm_sx1.py
36
@@ -XXX,XX +XXX,XX @@ def test_arm_sx1_initrd(self):
37
self.vm.add_args('-append', f'kunit.enable=0 rdinit=/sbin/init {self.CONSOLE_ARGS}')
38
self.vm.add_args('-no-reboot')
39
self.launch_kernel(zimage_path,
40
- initrd=initrd_path)
41
+ initrd=initrd_path,
42
+ wait_for='Boot successful')
43
self.vm.wait(timeout=120)
44
45
def test_arm_sx1_sd(self):
46
@@ -XXX,XX +XXX,XX @@ def test_arm_sx1_sd(self):
47
self.vm.add_args('-no-reboot')
48
self.vm.add_args('-snapshot')
49
self.vm.add_args('-drive', f'format=raw,if=sd,file={sd_fs_path}')
50
- self.launch_kernel(zimage_path)
51
+ self.launch_kernel(zimage_path, wait_for='Boot successful')
52
self.vm.wait(timeout=120)
53
54
def test_arm_sx1_flash(self):
55
@@ -XXX,XX +XXX,XX @@ def test_arm_sx1_flash(self):
56
self.vm.add_args('-no-reboot')
57
self.vm.add_args('-snapshot')
58
self.vm.add_args('-drive', f'format=raw,if=pflash,file={flash_path}')
59
- self.launch_kernel(zimage_path)
60
+ self.launch_kernel(zimage_path, wait_for='Boot successful')
61
self.vm.wait(timeout=120)
62
63
if __name__ == '__main__':
55
--
64
--
56
2.20.1
65
2.43.0
57
66
58
67
diff view generated by jsdifflib
1
In Arm v8.1M the VECTPENDING field in the ICSR has new behaviour: if
1
When we are calculating timer deadlines, the correct definition of
2
the register is accessed NonSecure and the highest priority pending
2
whether or not to apply an offset to the physical count is described
3
enabled exception (that would be returned in the VECTPENDING field)
3
in the Arm ARM DDI4087 rev L.a section D12.2.4.1. This is different
4
targets Secure, then the VECTPENDING field must read 1 rather than
4
from when the offset should be applied for a direct read of the
5
the exception number of the pending exception. Implement this.
5
counter sysreg.
6
6
7
We got this right for the EL1 physical timer and for the EL1 virtual
8
timer, but got all the rest wrong: they should be using a zero offset
9
always.
10
11
Factor the offset calculation out into a function that has a comment
12
documenting exactly which offset it is calculating and which gets the
13
HYP, SEC, and HYPVIRT cases right.
14
15
Cc: qemu-stable@nongnu.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Message-id: 20210723162146.5167-7-peter.maydell@linaro.org
18
Message-id: 20250204125009.2281315-2-peter.maydell@linaro.org
10
---
19
---
11
hw/intc/armv7m_nvic.c | 31 ++++++++++++++++++++++++-------
20
target/arm/helper.c | 29 +++++++++++++++++++++++++++--
12
1 file changed, 24 insertions(+), 7 deletions(-)
21
1 file changed, 27 insertions(+), 2 deletions(-)
13
22
14
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
23
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/armv7m_nvic.c
25
--- a/target/arm/helper.c
17
+++ b/hw/intc/armv7m_nvic.c
26
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_acknowledge_irq(void *opaque)
27
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_phys_cnt_offset(CPUARMState *env)
19
nvic_irq_update(s);
28
return gt_phys_raw_cnt_offset(env);
20
}
29
}
21
30
22
+static bool vectpending_targets_secure(NVICState *s)
31
+static uint64_t gt_indirect_access_timer_offset(CPUARMState *env, int timeridx)
23
+{
32
+{
24
+ /* Return true if s->vectpending targets Secure state */
33
+ /*
25
+ if (s->vectpending_is_s_banked) {
34
+ * Return the timer offset to use for indirect accesses to the timer.
26
+ return true;
35
+ * This is the Offset value as defined in D12.2.4.1 "Operation of the
36
+ * CompareValue views of the timers".
37
+ *
38
+ * The condition here is not always the same as the condition for
39
+ * whether to apply an offset register when doing a direct read of
40
+ * the counter sysreg; those conditions are described in the
41
+ * access pseudocode for each counter register.
42
+ */
43
+ switch (timeridx) {
44
+ case GTIMER_PHYS:
45
+ return gt_phys_raw_cnt_offset(env);
46
+ case GTIMER_VIRT:
47
+ return env->cp15.cntvoff_el2;
48
+ case GTIMER_HYP:
49
+ case GTIMER_SEC:
50
+ case GTIMER_HYPVIRT:
51
+ return 0;
52
+ default:
53
+ g_assert_not_reached();
27
+ }
54
+ }
28
+ return !exc_is_banked(s->vectpending) &&
29
+ exc_targets_secure(s, s->vectpending);
30
+}
55
+}
31
+
56
+
32
void armv7m_nvic_get_pending_irq_info(void *opaque,
57
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
33
int *pirq, bool *ptargets_secure)
34
{
58
{
35
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_get_pending_irq_info(void *opaque,
59
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
36
60
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
37
assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
61
* Timer enabled: calculate and set current ISTATUS, irq, and
38
62
* reset timer to when ISTATUS next has to change
39
- if (s->vectpending_is_s_banked) {
63
*/
40
- targets_secure = true;
64
- uint64_t offset = timeridx == GTIMER_VIRT ?
41
- } else {
65
- cpu->env.cp15.cntvoff_el2 : gt_phys_raw_cnt_offset(&cpu->env);
42
- targets_secure = !exc_is_banked(pending) &&
66
+ uint64_t offset = gt_indirect_access_timer_offset(&cpu->env, timeridx);
43
- exc_targets_secure(s, pending);
67
uint64_t count = gt_get_countervalue(&cpu->env);
44
- }
68
/* Note that this must be unsigned 64 bit arithmetic: */
45
+ targets_secure = vectpending_targets_secure(s);
69
int istatus = count - offset >= gt->cval;
46
47
trace_nvic_get_pending_irq_info(pending, targets_secure);
48
49
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
50
/* VECTACTIVE */
51
val = cpu->env.v7m.exception;
52
/* VECTPENDING */
53
- val |= (s->vectpending & 0x1ff) << 12;
54
+ if (s->vectpending) {
55
+ /*
56
+ * From v8.1M VECTPENDING must read as 1 if accessed as
57
+ * NonSecure and the highest priority pending and enabled
58
+ * exception targets Secure.
59
+ */
60
+ int vp = s->vectpending;
61
+ if (!attrs.secure && arm_feature(&cpu->env, ARM_FEATURE_V8_1M) &&
62
+ vectpending_targets_secure(s)) {
63
+ vp = 1;
64
+ }
65
+ val |= (vp & 0x1ff) << 12;
66
+ }
67
/* ISRPENDING - set if any external IRQ is pending */
68
if (nvic_isrpending(s)) {
69
val |= (1 << 22);
70
--
70
--
71
2.20.1
71
2.43.0
72
72
73
73
diff view generated by jsdifflib
1
The ISCR.ISRPENDING bit is set when an external interrupt is pending.
1
The CNTVOFF_EL2 offset register should only be applied for accessses
2
This is true whether that external interrupt is enabled or not.
2
to CNTVCT_EL0 and for the EL1 virtual timer (CNTV_*). We were
3
This means that we can't use 's->vectpending == 0' as a shortcut to
3
incorrectly applying it for the EL2 virtual timer (CNTHV_*).
4
"ISRPENDING is zero", because s->vectpending indicates only the
5
highest priority pending enabled interrupt.
6
4
7
Remove the incorrect optimization so that if there is no pending
5
Cc: qemu-stable@nongnu.org
8
enabled interrupt we fall through to scanning through the whole
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
interrupt array.
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Message-id: 20250204125009.2281315-3-peter.maydell@linaro.org
9
---
10
target/arm/helper.c | 2 --
11
1 file changed, 2 deletions(-)
10
12
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20210723162146.5167-5-peter.maydell@linaro.org
14
---
15
hw/intc/armv7m_nvic.c | 9 ++++-----
16
1 file changed, 4 insertions(+), 5 deletions(-)
17
18
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
19
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/intc/armv7m_nvic.c
15
--- a/target/arm/helper.c
21
+++ b/hw/intc/armv7m_nvic.c
16
+++ b/target/arm/helper.c
22
@@ -XXX,XX +XXX,XX @@ static bool nvic_isrpending(NVICState *s)
17
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
23
{
18
24
int irq;
19
switch (timeridx) {
25
20
case GTIMER_VIRT:
26
- /* We can shortcut if the highest priority pending interrupt
21
- case GTIMER_HYPVIRT:
27
- * happens to be external or if there is nothing pending.
22
offset = gt_virt_cnt_offset(env);
28
+ /*
23
break;
29
+ * We can shortcut if the highest priority pending interrupt
24
case GTIMER_PHYS:
30
+ * happens to be external; if not we need to check the whole
25
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
31
+ * vectors[] array.
26
32
*/
27
switch (timeridx) {
33
if (s->vectpending > NVIC_FIRST_IRQ) {
28
case GTIMER_VIRT:
34
return true;
29
- case GTIMER_HYPVIRT:
35
}
30
offset = gt_virt_cnt_offset(env);
36
- if (s->vectpending == 0) {
31
break;
37
- return false;
32
case GTIMER_PHYS:
38
- }
39
40
for (irq = NVIC_FIRST_IRQ; irq < s->num_irq; irq++) {
41
if (s->vectors[irq].pending) {
42
--
33
--
43
2.20.1
34
2.43.0
44
35
45
36
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
When we added Secure EL2 support, we missed that this needs an update
2
to the access code for the EL3 physical timer registers. These are
3
supposed to UNDEF from Secure EL1 when Secure EL2 is enabled.
2
4
3
Currently, our only caller is sve_zcr_len_for_el, which has
5
(Note for stable backporting: for backports to branches where
4
already masked the length extracted from ZCR_ELx, so the
6
CP_ACCESS_UNDEFINED is not defined, the old name to use instead
5
masking done here is a nop. But we will shortly have uses
7
is CP_ACCESS_TRAP_UNCATEGORIZED.)
6
from other locations, where the length will be unmasked.
7
8
8
Saturate the length to ARM_MAX_VQ instead of truncating to
9
Cc: qemu-stable@nongnu.org
9
the low 4 bits.
10
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Message-id: 20210723203344.968563-2-richard.henderson@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Message-id: 20250204125009.2281315-4-peter.maydell@linaro.org
15
---
13
---
16
target/arm/helper.c | 4 +++-
14
target/arm/helper.c | 3 +++
17
1 file changed, 3 insertions(+), 1 deletion(-)
15
1 file changed, 3 insertions(+)
18
16
19
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper.c
19
--- a/target/arm/helper.c
22
+++ b/target/arm/helper.c
20
+++ b/target/arm/helper.c
23
@@ -XXX,XX +XXX,XX @@ static uint32_t sve_zcr_get_valid_len(ARMCPU *cpu, uint32_t start_len)
21
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
24
{
22
if (!arm_is_secure(env)) {
25
uint32_t end_len;
23
return CP_ACCESS_UNDEFINED;
26
24
}
27
- end_len = start_len &= 0xf;
25
+ if (arm_is_el2_enabled(env)) {
28
+ start_len = MIN(start_len, ARM_MAX_VQ - 1);
26
+ return CP_ACCESS_UNDEFINED;
29
+ end_len = start_len;
27
+ }
30
+
28
if (!(env->cp15.scr_el3 & SCR_ST)) {
31
if (!test_bit(start_len, cpu->sve_vq_map)) {
29
return CP_ACCESS_TRAP_EL3;
32
end_len = find_last_bit(cpu->sve_vq_map, start_len);
30
}
33
assert(end_len < start_len);
34
--
31
--
35
2.20.1
32
2.43.0
36
33
37
34
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Currently we handle CNTV_TVAL_EL02 by calling gt_tval_read() for the
2
EL1 virt timer. This is almost correct, but the underlying
3
CNTV_TVAL_EL0 register behaves slightly differently. CNTV_TVAL_EL02
4
always applies the CNTVOFF_EL2 offset; CNTV_TVAL_EL0 doesn't do so if
5
we're at EL2 and HCR_EL2.E2H is 1.
2
6
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
We were getting this wrong, because we ended up in
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
gt_virt_cnt_offset() and did the E2H check.
5
Message-id: 20210726150953.1218690-1-f4bug@amsat.org
9
10
Factor out the tval read/write calculation from the selection of the
11
offset, so that we can special case gt_virt_tval_read() and
12
gt_virt_tval_write() to unconditionally pass CNTVOFF_EL2.
13
14
Cc: qemu-stable@nongnu.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
17
Message-id: 20250204125009.2281315-5-peter.maydell@linaro.org
7
---
18
---
8
hw/arm/nseries.c | 2 +-
19
target/arm/helper.c | 36 +++++++++++++++++++++++++++---------
9
1 file changed, 1 insertion(+), 1 deletion(-)
20
1 file changed, 27 insertions(+), 9 deletions(-)
10
21
11
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/nseries.c
24
--- a/target/arm/helper.c
14
+++ b/hw/arm/nseries.c
25
+++ b/target/arm/helper.c
15
@@ -XXX,XX +XXX,XX @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
26
@@ -XXX,XX +XXX,XX @@ static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
16
default:
27
gt_recalc_timer(env_archcpu(env), timeridx);
17
bad_cmd:
28
}
18
qemu_log_mask(LOG_GUEST_ERROR,
29
19
- "%s: unknown command %02x\n", __func__, s->cmd);
30
+static uint64_t do_tval_read(CPUARMState *env, int timeridx, uint64_t offset)
20
+ "%s: unknown command 0x%02x\n", __func__, s->cmd);
31
+{
32
+ return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
33
+ (gt_get_countervalue(env) - offset));
34
+}
35
+
36
static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
37
int timeridx)
38
{
39
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
21
break;
40
break;
22
}
41
}
23
42
43
- return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
44
- (gt_get_countervalue(env) - offset));
45
+ return do_tval_read(env, timeridx, offset);
46
+}
47
+
48
+static void do_tval_write(CPUARMState *env, int timeridx, uint64_t value,
49
+ uint64_t offset)
50
+{
51
+ trace_arm_gt_tval_write(timeridx, value);
52
+ env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) - offset +
53
+ sextract64(value, 0, 32);
54
+ gt_recalc_timer(env_archcpu(env), timeridx);
55
}
56
57
static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
58
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
59
offset = gt_phys_cnt_offset(env);
60
break;
61
}
62
-
63
- trace_arm_gt_tval_write(timeridx, value);
64
- env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) - offset +
65
- sextract64(value, 0, 32);
66
- gt_recalc_timer(env_archcpu(env), timeridx);
67
+ do_tval_write(env, timeridx, value, offset);
68
}
69
70
static void gt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
71
@@ -XXX,XX +XXX,XX @@ static void gt_virt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
72
73
static uint64_t gt_virt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
74
{
75
- return gt_tval_read(env, ri, GTIMER_VIRT);
76
+ /*
77
+ * This is CNTV_TVAL_EL02; unlike the underlying CNTV_TVAL_EL0
78
+ * we always apply CNTVOFF_EL2. Special case that here rather
79
+ * than going into the generic gt_tval_read() and then having
80
+ * to re-detect that it's this register.
81
+ * Note that the accessfn/perms mean we know we're at EL2 or EL3 here.
82
+ */
83
+ return do_tval_read(env, GTIMER_VIRT, env->cp15.cntvoff_el2);
84
}
85
86
static void gt_virt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
87
uint64_t value)
88
{
89
- gt_tval_write(env, ri, GTIMER_VIRT, value);
90
+ /* Similarly for writes to CNTV_TVAL_EL02 */
91
+ do_tval_write(env, GTIMER_VIRT, value, env->cp15.cntvoff_el2);
92
}
93
94
static void gt_virt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
24
--
95
--
25
2.20.1
96
2.43.0
26
97
27
98
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
When reading or writing the timer registers, sometimes we need to
2
2
apply one of the timer offsets. Specifically, this happens for
3
Rename from sve_zcr_get_valid_len and make accessible
3
direct reads of the counter registers CNTPCT_EL0 and CNTVCT_EL0 (and
4
from outside of helper.c.
4
their self-synchronized variants CNTVCTSS_EL0 and CNTPCTSS_EL0). It
5
5
also applies for direct reads and writes of the CNT*_TVAL_EL*
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
registers that provide the 32-bit downcounting view of each timer.
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
8
Message-id: 20210723203344.968563-3-richard.henderson@linaro.org
8
We currently do this with duplicated code in gt_tval_read() and
9
gt_tval_write() and a special-case in gt_virt_cnt_read() and
10
gt_cnt_read(). Refactor this so that we handle it all in a single
11
function gt_direct_access_timer_offset(), to parallel how we handle
12
the offset for indirect accesses.
13
14
The call in the WFIT helper previously to gt_virt_cnt_offset() is
15
now to gt_direct_access_timer_offset(); this is the correct
16
behaviour, but it's not immediately obvious that it shouldn't be
17
considered an indirect access, so we add an explanatory comment.
18
19
This commit should make no behavioural changes.
20
21
(Cc to stable because the following bugfix commit will
22
depend on this one.)
23
24
Cc: qemu-stable@nongnu.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
27
Message-id: 20250204125009.2281315-6-peter.maydell@linaro.org
10
---
28
---
11
target/arm/internals.h | 10 ++++++++++
29
target/arm/internals.h | 5 +-
12
target/arm/helper.c | 4 ++--
30
target/arm/helper.c | 103 +++++++++++++++++++------------------
13
2 files changed, 12 insertions(+), 2 deletions(-)
31
target/arm/tcg/op_helper.c | 8 ++-
32
3 files changed, 62 insertions(+), 54 deletions(-)
14
33
15
diff --git a/target/arm/internals.h b/target/arm/internals.h
34
diff --git a/target/arm/internals.h b/target/arm/internals.h
16
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/internals.h
36
--- a/target/arm/internals.h
18
+++ b/target/arm/internals.h
37
+++ b/target/arm/internals.h
19
@@ -XXX,XX +XXX,XX @@ void arm_translate_init(void);
38
@@ -XXX,XX +XXX,XX @@ int delete_hw_watchpoint(target_ulong addr, target_ulong len, int type);
20
void arm_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb);
39
uint64_t gt_get_countervalue(CPUARMState *env);
21
#endif /* CONFIG_TCG */
40
/*
22
41
* Return the currently applicable offset between the system counter
23
+/**
42
- * and CNTVCT_EL0 (this will be either 0 or the value of CNTVOFF_EL2).
24
+ * aarch64_sve_zcr_get_valid_len:
43
+ * and the counter for the specified timer, as used for direct register
25
+ * @cpu: cpu context
44
+ * accesses.
26
+ * @start_len: maximum len to consider
45
*/
27
+ *
46
-uint64_t gt_virt_cnt_offset(CPUARMState *env);
28
+ * Return the maximum supported sve vector length <= @start_len.
47
+uint64_t gt_direct_access_timer_offset(CPUARMState *env, int timeridx);
29
+ * Note that both @start_len and the return value are in units
48
30
+ * of ZCR_ELx.LEN, so the vector bit length is (x + 1) * 128.
49
/*
31
+ */
50
* Return mask of ARMMMUIdxBit values corresponding to an "invalidate
32
+uint32_t aarch64_sve_zcr_get_valid_len(ARMCPU *cpu, uint32_t start_len);
33
34
enum arm_fprounding {
35
FPROUNDING_TIEEVEN,
36
diff --git a/target/arm/helper.c b/target/arm/helper.c
51
diff --git a/target/arm/helper.c b/target/arm/helper.c
37
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/helper.c
53
--- a/target/arm/helper.c
39
+++ b/target/arm/helper.c
54
+++ b/target/arm/helper.c
40
@@ -XXX,XX +XXX,XX @@ int sve_exception_el(CPUARMState *env, int el)
55
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_phys_raw_cnt_offset(CPUARMState *env)
41
return 0;
56
return 0;
42
}
57
}
43
58
44
-static uint32_t sve_zcr_get_valid_len(ARMCPU *cpu, uint32_t start_len)
59
-static uint64_t gt_phys_cnt_offset(CPUARMState *env)
45
+uint32_t aarch64_sve_zcr_get_valid_len(ARMCPU *cpu, uint32_t start_len)
60
-{
46
{
61
- if (arm_current_el(env) >= 2) {
47
uint32_t end_len;
62
- return 0;
48
63
- }
49
@@ -XXX,XX +XXX,XX @@ uint32_t sve_zcr_len_for_el(CPUARMState *env, int el)
64
- return gt_phys_raw_cnt_offset(env);
50
zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[3]);
65
-}
66
-
67
static uint64_t gt_indirect_access_timer_offset(CPUARMState *env, int timeridx)
68
{
69
/*
70
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_indirect_access_timer_offset(CPUARMState *env, int timeridx)
51
}
71
}
52
72
}
53
- return sve_zcr_get_valid_len(cpu, zcr_len);
73
54
+ return aarch64_sve_zcr_get_valid_len(cpu, zcr_len);
74
+uint64_t gt_direct_access_timer_offset(CPUARMState *env, int timeridx)
55
}
75
+{
56
76
+ /*
57
static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
77
+ * Return the timer offset to use for direct accesses to the
78
+ * counter registers CNTPCT and CNTVCT, and for direct accesses
79
+ * to the CNT*_TVAL registers.
80
+ *
81
+ * This isn't exactly the same as the indirect-access offset,
82
+ * because here we also care about what EL the register access
83
+ * is being made from.
84
+ *
85
+ * This corresponds to the access pseudocode for the registers.
86
+ */
87
+ uint64_t hcr;
88
+
89
+ switch (timeridx) {
90
+ case GTIMER_PHYS:
91
+ if (arm_current_el(env) >= 2) {
92
+ return 0;
93
+ }
94
+ return gt_phys_raw_cnt_offset(env);
95
+ case GTIMER_VIRT:
96
+ switch (arm_current_el(env)) {
97
+ case 2:
98
+ hcr = arm_hcr_el2_eff(env);
99
+ if (hcr & HCR_E2H) {
100
+ return 0;
101
+ }
102
+ break;
103
+ case 0:
104
+ hcr = arm_hcr_el2_eff(env);
105
+ if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
106
+ return 0;
107
+ }
108
+ break;
109
+ }
110
+ return env->cp15.cntvoff_el2;
111
+ case GTIMER_HYP:
112
+ case GTIMER_SEC:
113
+ case GTIMER_HYPVIRT:
114
+ return 0;
115
+ default:
116
+ g_assert_not_reached();
117
+ }
118
+}
119
+
120
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
121
{
122
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
123
@@ -XXX,XX +XXX,XX @@ static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri,
124
125
static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
126
{
127
- return gt_get_countervalue(env) - gt_phys_cnt_offset(env);
128
-}
129
-
130
-uint64_t gt_virt_cnt_offset(CPUARMState *env)
131
-{
132
- uint64_t hcr;
133
-
134
- switch (arm_current_el(env)) {
135
- case 2:
136
- hcr = arm_hcr_el2_eff(env);
137
- if (hcr & HCR_E2H) {
138
- return 0;
139
- }
140
- break;
141
- case 0:
142
- hcr = arm_hcr_el2_eff(env);
143
- if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
144
- return 0;
145
- }
146
- break;
147
- }
148
-
149
- return env->cp15.cntvoff_el2;
150
+ uint64_t offset = gt_direct_access_timer_offset(env, GTIMER_PHYS);
151
+ return gt_get_countervalue(env) - offset;
152
}
153
154
static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
155
{
156
- return gt_get_countervalue(env) - gt_virt_cnt_offset(env);
157
+ uint64_t offset = gt_direct_access_timer_offset(env, GTIMER_VIRT);
158
+ return gt_get_countervalue(env) - offset;
159
}
160
161
static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
162
@@ -XXX,XX +XXX,XX @@ static uint64_t do_tval_read(CPUARMState *env, int timeridx, uint64_t offset)
163
static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
164
int timeridx)
165
{
166
- uint64_t offset = 0;
167
-
168
- switch (timeridx) {
169
- case GTIMER_VIRT:
170
- offset = gt_virt_cnt_offset(env);
171
- break;
172
- case GTIMER_PHYS:
173
- offset = gt_phys_cnt_offset(env);
174
- break;
175
- }
176
+ uint64_t offset = gt_direct_access_timer_offset(env, timeridx);
177
178
return do_tval_read(env, timeridx, offset);
179
}
180
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
181
int timeridx,
182
uint64_t value)
183
{
184
- uint64_t offset = 0;
185
+ uint64_t offset = gt_direct_access_timer_offset(env, timeridx);
186
187
- switch (timeridx) {
188
- case GTIMER_VIRT:
189
- offset = gt_virt_cnt_offset(env);
190
- break;
191
- case GTIMER_PHYS:
192
- offset = gt_phys_cnt_offset(env);
193
- break;
194
- }
195
do_tval_write(env, timeridx, value, offset);
196
}
197
198
diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
199
index XXXXXXX..XXXXXXX 100644
200
--- a/target/arm/tcg/op_helper.c
201
+++ b/target/arm/tcg/op_helper.c
202
@@ -XXX,XX +XXX,XX @@ void HELPER(wfit)(CPUARMState *env, uint64_t timeout)
203
int target_el = check_wfx_trap(env, false, &excp);
204
/* The WFIT should time out when CNTVCT_EL0 >= the specified value. */
205
uint64_t cntval = gt_get_countervalue(env);
206
- uint64_t offset = gt_virt_cnt_offset(env);
207
+ /*
208
+ * We want the value that we would get if we read CNTVCT_EL0 from
209
+ * the current exception level, so the direct_access offset, not
210
+ * the indirect_access one. Compare the pseudocode LocalTimeoutEvent(),
211
+ * which calls VirtualCounterTimer().
212
+ */
213
+ uint64_t offset = gt_direct_access_timer_offset(env, GTIMER_VIRT);
214
uint64_t cntvct = cntval - offset;
215
uint64_t nexttick;
216
58
--
217
--
59
2.20.1
218
2.43.0
60
219
61
220
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Alex Bennée <alex.bennee@linaro.org>
2
2
3
Mirror the behavour of /proc/sys/abi/sve_default_vector_length
3
When FEAT_SEL2 was implemented the SEL2 timers were missed. This
4
under the real linux kernel. We have no way of passing along
4
shows up when building the latest Hafnium with SPMC_AT_EL=2. The
5
a real default across exec like the kernel can, but this is a
5
actual implementation utilises the same logic as the rest of the
6
decent way of adjusting the startup vector length of a process.
6
timers so all we need to do is:
7
7
8
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/482
8
- define the timers and their access functions
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
- conditionally add the correct system registers
10
- create a new accessfn as the rules are subtly different to the
11
existing secure timer
12
13
Fixes: e9152ee91c (target/arm: add ARMv8.4-SEL2 system registers)
14
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20210723203344.968563-4-richard.henderson@linaro.org
17
Message-id: 20250204125009.2281315-7-peter.maydell@linaro.org
12
[PMM: tweaked docs formatting, document -1 special-case,
18
Cc: qemu-stable@nongnu.org
13
added fixup patch from RTH mentioning QEMU's maximum veclen.]
19
Cc: Andrei Homescu <ahomescu@google.com>
20
Cc: Arve Hjønnevåg <arve@google.com>
21
Cc: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
22
[PMM: CP_ACCESS_TRAP_UNCATEGORIZED -> CP_ACCESS_UNDEFINED;
23
offset logic now in gt_{indirect,direct}_access_timer_offset() ]
24
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
26
---
16
docs/system/arm/cpu-features.rst | 15 ++++++++
27
include/hw/arm/bsa.h | 2 +
17
target/arm/cpu.h | 5 +++
28
target/arm/cpu.h | 2 +
18
target/arm/cpu.c | 14 ++++++--
29
target/arm/gtimer.h | 4 +-
19
target/arm/cpu64.c | 60 ++++++++++++++++++++++++++++++++
30
target/arm/cpu.c | 4 ++
20
4 files changed, 92 insertions(+), 2 deletions(-)
31
target/arm/helper.c | 163 +++++++++++++++++++++++++++++++++++++++++++
21
32
5 files changed, 174 insertions(+), 1 deletion(-)
22
diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst
33
23
index XXXXXXX..XXXXXXX 100644
34
diff --git a/include/hw/arm/bsa.h b/include/hw/arm/bsa.h
24
--- a/docs/system/arm/cpu-features.rst
35
index XXXXXXX..XXXXXXX 100644
25
+++ b/docs/system/arm/cpu-features.rst
36
--- a/include/hw/arm/bsa.h
26
@@ -XXX,XX +XXX,XX @@ verbose command lines. However, the recommended way to select vector
37
+++ b/include/hw/arm/bsa.h
27
lengths is to explicitly enable each desired length. Therefore only
38
@@ -XXX,XX +XXX,XX @@
28
example's (1), (4), and (6) exhibit recommended uses of the properties.
39
#define QEMU_ARM_BSA_H
29
40
30
+SVE User-mode Default Vector Length Property
41
/* These are architectural INTID values */
31
+--------------------------------------------
42
+#define ARCH_TIMER_S_EL2_VIRT_IRQ 19
32
+
43
+#define ARCH_TIMER_S_EL2_IRQ 20
33
+For qemu-aarch64, the cpu property ``sve-default-vector-length=N`` is
44
#define VIRTUAL_PMU_IRQ 23
34
+defined to mirror the Linux kernel parameter file
45
#define ARCH_GIC_MAINT_IRQ 25
35
+``/proc/sys/abi/sve_default_vector_length``. The default length, ``N``,
46
#define ARCH_TIMER_NS_EL2_IRQ 26
36
+is in units of bytes and must be between 16 and 8192.
37
+If not specified, the default vector length is 64.
38
+
39
+If the default length is larger than the maximum vector length enabled,
40
+the actual vector length will be reduced. Note that the maximum vector
41
+length supported by QEMU is 256.
42
+
43
+If this property is set to ``-1`` then the default vector length
44
+is set to the maximum possible length.
45
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
47
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
46
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/cpu.h
49
--- a/target/arm/cpu.h
48
+++ b/target/arm/cpu.h
50
+++ b/target/arm/cpu.h
49
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
51
@@ -XXX,XX +XXX,XX @@ void arm_gt_vtimer_cb(void *opaque);
50
/* Used to set the maximum vector length the cpu will support. */
52
void arm_gt_htimer_cb(void *opaque);
51
uint32_t sve_max_vq;
53
void arm_gt_stimer_cb(void *opaque);
52
54
void arm_gt_hvtimer_cb(void *opaque);
53
+#ifdef CONFIG_USER_ONLY
55
+void arm_gt_sel2timer_cb(void *opaque);
54
+ /* Used to set the default vector length at process start. */
56
+void arm_gt_sel2vtimer_cb(void *opaque);
55
+ uint32_t sve_default_vq;
57
56
+#endif
58
unsigned int gt_cntfrq_period_ns(ARMCPU *cpu);
57
+
59
void gt_rme_post_el_change(ARMCPU *cpu, void *opaque);
58
/*
60
diff --git a/target/arm/gtimer.h b/target/arm/gtimer.h
59
* In sve_vq_map each set bit is a supported vector length of
61
index XXXXXXX..XXXXXXX 100644
60
* (bit-number + 1) * 16 bytes, i.e. each bit number + 1 is the vector
62
--- a/target/arm/gtimer.h
63
+++ b/target/arm/gtimer.h
64
@@ -XXX,XX +XXX,XX @@ enum {
65
GTIMER_HYP = 2,
66
GTIMER_SEC = 3,
67
GTIMER_HYPVIRT = 4,
68
-#define NUM_GTIMERS 5
69
+ GTIMER_S_EL2_PHYS = 5, /* CNTHPS_* ; only if FEAT_SEL2 */
70
+ GTIMER_S_EL2_VIRT = 6, /* CNTHVS_* ; only if FEAT_SEL2 */
71
+#define NUM_GTIMERS 7
72
};
73
74
#endif
61
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
75
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
62
index XXXXXXX..XXXXXXX 100644
76
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/cpu.c
77
--- a/target/arm/cpu.c
64
+++ b/target/arm/cpu.c
78
+++ b/target/arm/cpu.c
65
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
79
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
66
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 16, 2, 3);
80
arm_gt_stimer_cb, cpu);
67
/* with reasonable vector length */
81
cpu->gt_timer[GTIMER_HYPVIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
68
if (cpu_isar_feature(aa64_sve, cpu)) {
82
arm_gt_hvtimer_cb, cpu);
69
- env->vfp.zcr_el[1] = MIN(cpu->sve_max_vq - 1, 3);
83
+ cpu->gt_timer[GTIMER_S_EL2_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
70
+ env->vfp.zcr_el[1] =
84
+ arm_gt_sel2timer_cb, cpu);
71
+ aarch64_sve_zcr_get_valid_len(cpu, cpu->sve_default_vq - 1);
85
+ cpu->gt_timer[GTIMER_S_EL2_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
72
}
86
+ arm_gt_sel2vtimer_cb, cpu);
73
/*
87
}
74
* Enable TBI0 but not TBI1.
88
#endif
75
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_initfn(Object *obj)
89
76
QLIST_INIT(&cpu->pre_el_change_hooks);
90
diff --git a/target/arm/helper.c b/target/arm/helper.c
77
QLIST_INIT(&cpu->el_change_hooks);
91
index XXXXXXX..XXXXXXX 100644
78
92
--- a/target/arm/helper.c
79
-#ifndef CONFIG_USER_ONLY
93
+++ b/target/arm/helper.c
80
+#ifdef CONFIG_USER_ONLY
94
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
81
+# ifdef TARGET_AARCH64
95
}
96
}
97
98
+static CPAccessResult gt_sel2timer_access(CPUARMState *env,
99
+ const ARMCPRegInfo *ri,
100
+ bool isread)
101
+{
82
+ /*
102
+ /*
83
+ * The linux kernel defaults to 512-bit vectors, when sve is supported.
103
+ * The AArch64 register view of the secure EL2 timers are mostly
84
+ * See documentation for /proc/sys/abi/sve_default_vector_length, and
104
+ * accessible from EL3 and EL2 although can also be trapped to EL2
85
+ * our corresponding sve-default-vector-length cpu property.
105
+ * from EL1 depending on nested virt config.
86
+ */
106
+ */
87
+ cpu->sve_default_vq = 4;
107
+ switch (arm_current_el(env)) {
88
+# endif
108
+ case 0: /* UNDEFINED */
89
+#else
109
+ return CP_ACCESS_UNDEFINED;
90
/* Our inbound IRQ and FIQ lines */
110
+ case 1:
91
if (kvm_enabled()) {
111
+ if (!arm_is_secure(env)) {
92
/* VIRQ and VFIQ are unused with KVM but we add them to maintain
112
+ /* UNDEFINED */
93
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
113
+ return CP_ACCESS_UNDEFINED;
94
index XXXXXXX..XXXXXXX 100644
114
+ } else if (arm_hcr_el2_eff(env) & HCR_NV) {
95
--- a/target/arm/cpu64.c
115
+ /* Aarch64.SystemAccessTrap(EL2, 0x18) */
96
+++ b/target/arm/cpu64.c
116
+ return CP_ACCESS_TRAP_EL2;
97
@@ -XXX,XX +XXX,XX @@ static void cpu_arm_set_sve(Object *obj, bool value, Error **errp)
117
+ }
98
cpu->isar.id_aa64pfr0 = t;
118
+ /* UNDEFINED */
119
+ return CP_ACCESS_UNDEFINED;
120
+ case 2:
121
+ if (!arm_is_secure(env)) {
122
+ /* UNDEFINED */
123
+ return CP_ACCESS_UNDEFINED;
124
+ }
125
+ return CP_ACCESS_OK;
126
+ case 3:
127
+ if (env->cp15.scr_el3 & SCR_EEL2) {
128
+ return CP_ACCESS_OK;
129
+ } else {
130
+ return CP_ACCESS_UNDEFINED;
131
+ }
132
+ default:
133
+ g_assert_not_reached();
134
+ }
135
+}
136
+
137
uint64_t gt_get_countervalue(CPUARMState *env)
138
{
139
ARMCPU *cpu = env_archcpu(env);
140
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_indirect_access_timer_offset(CPUARMState *env, int timeridx)
141
case GTIMER_HYP:
142
case GTIMER_SEC:
143
case GTIMER_HYPVIRT:
144
+ case GTIMER_S_EL2_PHYS:
145
+ case GTIMER_S_EL2_VIRT:
146
return 0;
147
default:
148
g_assert_not_reached();
149
@@ -XXX,XX +XXX,XX @@ uint64_t gt_direct_access_timer_offset(CPUARMState *env, int timeridx)
150
case GTIMER_HYP:
151
case GTIMER_SEC:
152
case GTIMER_HYPVIRT:
153
+ case GTIMER_S_EL2_PHYS:
154
+ case GTIMER_S_EL2_VIRT:
155
return 0;
156
default:
157
g_assert_not_reached();
158
@@ -XXX,XX +XXX,XX @@ static void gt_sec_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
159
gt_ctl_write(env, ri, GTIMER_SEC, value);
99
}
160
}
100
161
101
+#ifdef CONFIG_USER_ONLY
162
+static void gt_sec_pel2_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
102
+/* Mirror linux /proc/sys/abi/sve_default_vector_length. */
163
+{
103
+static void cpu_arm_set_sve_default_vec_len(Object *obj, Visitor *v,
164
+ gt_timer_reset(env, ri, GTIMER_S_EL2_PHYS);
104
+ const char *name, void *opaque,
165
+}
105
+ Error **errp)
166
+
106
+{
167
+static void gt_sec_pel2_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
107
+ ARMCPU *cpu = ARM_CPU(obj);
168
+ uint64_t value)
108
+ int32_t default_len, default_vq, remainder;
169
+{
109
+
170
+ gt_cval_write(env, ri, GTIMER_S_EL2_PHYS, value);
110
+ if (!visit_type_int32(v, name, &default_len, errp)) {
171
+}
111
+ return;
172
+
112
+ }
173
+static uint64_t gt_sec_pel2_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
113
+
174
+{
114
+ /* Undocumented, but the kernel allows -1 to indicate "maximum". */
175
+ return gt_tval_read(env, ri, GTIMER_S_EL2_PHYS);
115
+ if (default_len == -1) {
176
+}
116
+ cpu->sve_default_vq = ARM_MAX_VQ;
177
+
117
+ return;
178
+static void gt_sec_pel2_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
118
+ }
179
+ uint64_t value)
119
+
180
+{
120
+ default_vq = default_len / 16;
181
+ gt_tval_write(env, ri, GTIMER_S_EL2_PHYS, value);
121
+ remainder = default_len % 16;
182
+}
122
+
183
+
123
+ /*
184
+static void gt_sec_pel2_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
124
+ * Note that the 512 max comes from include/uapi/asm/sve_context.h
185
+ uint64_t value)
125
+ * and is the maximum architectural width of ZCR_ELx.LEN.
186
+{
126
+ */
187
+ gt_ctl_write(env, ri, GTIMER_S_EL2_PHYS, value);
127
+ if (remainder || default_vq < 1 || default_vq > 512) {
188
+}
128
+ error_setg(errp, "cannot set sve-default-vector-length");
189
+
129
+ if (remainder) {
190
+static void gt_sec_vel2_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
130
+ error_append_hint(errp, "Vector length not a multiple of 16\n");
191
+{
131
+ } else if (default_vq < 1) {
192
+ gt_timer_reset(env, ri, GTIMER_S_EL2_VIRT);
132
+ error_append_hint(errp, "Vector length smaller than 16\n");
193
+}
133
+ } else {
194
+
134
+ error_append_hint(errp, "Vector length larger than %d\n",
195
+static void gt_sec_vel2_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
135
+ 512 * 16);
196
+ uint64_t value)
136
+ }
197
+{
137
+ return;
198
+ gt_cval_write(env, ri, GTIMER_S_EL2_VIRT, value);
138
+ }
199
+}
139
+
200
+
140
+ cpu->sve_default_vq = default_vq;
201
+static uint64_t gt_sec_vel2_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
141
+}
202
+{
142
+
203
+ return gt_tval_read(env, ri, GTIMER_S_EL2_VIRT);
143
+static void cpu_arm_get_sve_default_vec_len(Object *obj, Visitor *v,
204
+}
144
+ const char *name, void *opaque,
205
+
145
+ Error **errp)
206
+static void gt_sec_vel2_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
146
+{
207
+ uint64_t value)
147
+ ARMCPU *cpu = ARM_CPU(obj);
208
+{
148
+ int32_t value = cpu->sve_default_vq * 16;
209
+ gt_tval_write(env, ri, GTIMER_S_EL2_VIRT, value);
149
+
210
+}
150
+ visit_type_int32(v, name, &value, errp);
211
+
151
+}
212
+static void gt_sec_vel2_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
213
+ uint64_t value)
214
+{
215
+ gt_ctl_write(env, ri, GTIMER_S_EL2_VIRT, value);
216
+}
217
+
218
static void gt_hv_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
219
{
220
gt_timer_reset(env, ri, GTIMER_HYPVIRT);
221
@@ -XXX,XX +XXX,XX @@ void arm_gt_stimer_cb(void *opaque)
222
gt_recalc_timer(cpu, GTIMER_SEC);
223
}
224
225
+void arm_gt_sel2timer_cb(void *opaque)
226
+{
227
+ ARMCPU *cpu = opaque;
228
+
229
+ gt_recalc_timer(cpu, GTIMER_S_EL2_PHYS);
230
+}
231
+
232
+void arm_gt_sel2vtimer_cb(void *opaque)
233
+{
234
+ ARMCPU *cpu = opaque;
235
+
236
+ gt_recalc_timer(cpu, GTIMER_S_EL2_VIRT);
237
+}
238
+
239
void arm_gt_hvtimer_cb(void *opaque)
240
{
241
ARMCPU *cpu = opaque;
242
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_sec_cp_reginfo[] = {
243
.access = PL2_RW, .accessfn = sel2_access,
244
.nv2_redirect_offset = 0x48,
245
.fieldoffset = offsetof(CPUARMState, cp15.vstcr_el2) },
246
+#ifndef CONFIG_USER_ONLY
247
+ /* Secure EL2 Physical Timer */
248
+ { .name = "CNTHPS_TVAL_EL2", .state = ARM_CP_STATE_AA64,
249
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 5, .opc2 = 0,
250
+ .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL2_RW,
251
+ .accessfn = gt_sel2timer_access,
252
+ .readfn = gt_sec_pel2_tval_read,
253
+ .writefn = gt_sec_pel2_tval_write,
254
+ .resetfn = gt_sec_pel2_timer_reset,
255
+ },
256
+ { .name = "CNTHPS_CTL_EL2", .state = ARM_CP_STATE_AA64,
257
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 5, .opc2 = 1,
258
+ .type = ARM_CP_IO, .access = PL2_RW,
259
+ .accessfn = gt_sel2timer_access,
260
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_S_EL2_PHYS].ctl),
261
+ .resetvalue = 0,
262
+ .writefn = gt_sec_pel2_ctl_write, .raw_writefn = raw_write,
263
+ },
264
+ { .name = "CNTHPS_CVAL_EL2", .state = ARM_CP_STATE_AA64,
265
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 5, .opc2 = 2,
266
+ .type = ARM_CP_IO, .access = PL2_RW,
267
+ .accessfn = gt_sel2timer_access,
268
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_S_EL2_PHYS].cval),
269
+ .writefn = gt_sec_pel2_cval_write, .raw_writefn = raw_write,
270
+ },
271
+ /* Secure EL2 Virtual Timer */
272
+ { .name = "CNTHVS_TVAL_EL2", .state = ARM_CP_STATE_AA64,
273
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 4, .opc2 = 0,
274
+ .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL2_RW,
275
+ .accessfn = gt_sel2timer_access,
276
+ .readfn = gt_sec_vel2_tval_read,
277
+ .writefn = gt_sec_vel2_tval_write,
278
+ .resetfn = gt_sec_vel2_timer_reset,
279
+ },
280
+ { .name = "CNTHVS_CTL_EL2", .state = ARM_CP_STATE_AA64,
281
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 4, .opc2 = 1,
282
+ .type = ARM_CP_IO, .access = PL2_RW,
283
+ .accessfn = gt_sel2timer_access,
284
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_S_EL2_VIRT].ctl),
285
+ .resetvalue = 0,
286
+ .writefn = gt_sec_vel2_ctl_write, .raw_writefn = raw_write,
287
+ },
288
+ { .name = "CNTHVS_CVAL_EL2", .state = ARM_CP_STATE_AA64,
289
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 4, .opc2 = 2,
290
+ .type = ARM_CP_IO, .access = PL2_RW,
291
+ .accessfn = gt_sel2timer_access,
292
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_S_EL2_VIRT].cval),
293
+ .writefn = gt_sec_vel2_cval_write, .raw_writefn = raw_write,
294
+ },
152
+#endif
295
+#endif
153
+
296
};
154
void aarch64_add_sve_properties(Object *obj)
297
155
{
298
static CPAccessResult nsacr_access(CPUARMState *env, const ARMCPRegInfo *ri,
156
uint32_t vq;
157
@@ -XXX,XX +XXX,XX @@ void aarch64_add_sve_properties(Object *obj)
158
object_property_add(obj, name, "bool", cpu_arm_get_sve_vq,
159
cpu_arm_set_sve_vq, NULL, NULL);
160
}
161
+
162
+#ifdef CONFIG_USER_ONLY
163
+ /* Mirror linux /proc/sys/abi/sve_default_vector_length. */
164
+ object_property_add(obj, "sve-default-vector-length", "int32",
165
+ cpu_arm_get_sve_default_vec_len,
166
+ cpu_arm_set_sve_default_vec_len, NULL, NULL);
167
+#endif
168
}
169
170
void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
171
--
299
--
172
2.20.1
300
2.43.0
173
301
174
302
diff view generated by jsdifflib
1
From: Joe Komlodi <joe.komlodi@xilinx.com>
1
From: Alex Bennée <alex.bennee@linaro.org>
2
2
3
The bit to see if a CD is valid is the last bit of the first word of the CD.
3
As we are about to add more physical and virtual timers let's make it
4
clear what each timer does.
4
5
5
Signed-off-by: Joe Komlodi <joe.komlodi@xilinx.com>
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
6
Message-id: 1626728232-134665-2-git-send-email-joe.komlodi@xilinx.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20250204125009.2281315-8-peter.maydell@linaro.org
10
[PMM: Add timer register name prefix to each comment]
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
13
---
10
hw/arm/smmuv3-internal.h | 2 +-
14
target/arm/gtimer.h | 10 +++++-----
11
1 file changed, 1 insertion(+), 1 deletion(-)
15
1 file changed, 5 insertions(+), 5 deletions(-)
12
16
13
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
17
diff --git a/target/arm/gtimer.h b/target/arm/gtimer.h
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/smmuv3-internal.h
19
--- a/target/arm/gtimer.h
16
+++ b/hw/arm/smmuv3-internal.h
20
+++ b/target/arm/gtimer.h
17
@@ -XXX,XX +XXX,XX @@ static inline int pa_range(STE *ste)
21
@@ -XXX,XX +XXX,XX @@
18
22
#define TARGET_ARM_GTIMER_H
19
/* CD fields */
23
20
24
enum {
21
-#define CD_VALID(x) extract32((x)->word[0], 30, 1)
25
- GTIMER_PHYS = 0,
22
+#define CD_VALID(x) extract32((x)->word[0], 31, 1)
26
- GTIMER_VIRT = 1,
23
#define CD_ASID(x) extract32((x)->word[1], 16, 16)
27
- GTIMER_HYP = 2,
24
#define CD_TTB(x, sel) \
28
- GTIMER_SEC = 3,
25
({ \
29
- GTIMER_HYPVIRT = 4,
30
+ GTIMER_PHYS = 0, /* CNTP_* ; EL1 physical timer */
31
+ GTIMER_VIRT = 1, /* CNTV_* ; EL1 virtual timer */
32
+ GTIMER_HYP = 2, /* CNTHP_* ; EL2 physical timer */
33
+ GTIMER_SEC = 3, /* CNTPS_* ; EL3 physical timer */
34
+ GTIMER_HYPVIRT = 4, /* CNTHV_* ; EL2 virtual timer ; only if FEAT_VHE */
35
GTIMER_S_EL2_PHYS = 5, /* CNTHPS_* ; only if FEAT_SEL2 */
36
GTIMER_S_EL2_VIRT = 6, /* CNTHVS_* ; only if FEAT_SEL2 */
37
#define NUM_GTIMERS 7
26
--
38
--
27
2.20.1
39
2.43.0
28
40
29
41
diff view generated by jsdifflib
1
The documentation of the -machine memory-backend has some minor
1
From: Alex Bennée <alex.bennee@linaro.org>
2
formatting errors:
3
* Misindentation of the initial line meant that the whole option
4
section is incorrectly indented in the HTML output compared to
5
the other -machine options
6
* The examples weren't indented, which meant that they were formatted
7
as plain run-on text including outputting the "::" as text.
8
* The a) b) list has no rst-format markup so it is rendered as
9
a single run-on paragraph
10
2
11
Fix the formatting.
3
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Message-id: 20250204125009.2281315-9-peter.maydell@linaro.org
7
Cc: qemu-stable@nongnu.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/arm/virt.c | 2 ++
12
1 file changed, 2 insertions(+)
12
13
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
14
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
15
Message-id: 20210719105257.3599-1-peter.maydell@linaro.org
16
---
17
qemu-options.hx | 30 +++++++++++++++++-------------
18
1 file changed, 17 insertions(+), 13 deletions(-)
19
20
diff --git a/qemu-options.hx b/qemu-options.hx
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/qemu-options.hx
16
--- a/hw/arm/virt.c
23
+++ b/qemu-options.hx
17
+++ b/hw/arm/virt.c
24
@@ -XXX,XX +XXX,XX @@ SRST
18
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
25
Enables or disables ACPI Heterogeneous Memory Attribute Table
19
[GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
26
(HMAT) support. The default is off.
20
[GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
27
21
[GTIMER_HYPVIRT] = ARCH_TIMER_NS_EL2_VIRT_IRQ,
28
- ``memory-backend='id'``
22
+ [GTIMER_S_EL2_PHYS] = ARCH_TIMER_S_EL2_IRQ,
29
+ ``memory-backend='id'``
23
+ [GTIMER_S_EL2_VIRT] = ARCH_TIMER_S_EL2_VIRT_IRQ,
30
An alternative to legacy ``-mem-path`` and ``mem-prealloc`` options.
24
};
31
Allows to use a memory backend as main RAM.
25
32
26
for (unsigned irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
33
For example:
34
::
35
- -object memory-backend-file,id=pc.ram,size=512M,mem-path=/hugetlbfs,prealloc=on,share=on
36
- -machine memory-backend=pc.ram
37
- -m 512M
38
+
39
+ -object memory-backend-file,id=pc.ram,size=512M,mem-path=/hugetlbfs,prealloc=on,share=on
40
+ -machine memory-backend=pc.ram
41
+ -m 512M
42
43
Migration compatibility note:
44
- a) as backend id one shall use value of 'default-ram-id', advertised by
45
- machine type (available via ``query-machines`` QMP command), if migration
46
- to/from old QEMU (<5.0) is expected.
47
- b) for machine types 4.0 and older, user shall
48
- use ``x-use-canonical-path-for-ramblock-id=off`` backend option
49
- if migration to/from old QEMU (<5.0) is expected.
50
+
51
+ * as backend id one shall use value of 'default-ram-id', advertised by
52
+ machine type (available via ``query-machines`` QMP command), if migration
53
+ to/from old QEMU (<5.0) is expected.
54
+ * for machine types 4.0 and older, user shall
55
+ use ``x-use-canonical-path-for-ramblock-id=off`` backend option
56
+ if migration to/from old QEMU (<5.0) is expected.
57
+
58
For example:
59
::
60
- -object memory-backend-ram,id=pc.ram,size=512M,x-use-canonical-path-for-ramblock-id=off
61
- -machine memory-backend=pc.ram
62
- -m 512M
63
+
64
+ -object memory-backend-ram,id=pc.ram,size=512M,x-use-canonical-path-for-ramblock-id=off
65
+ -machine memory-backend=pc.ram
66
+ -m 512M
67
ERST
68
69
HXCOMM Deprecated by -machine
70
--
27
--
71
2.20.1
28
2.43.0
72
29
73
30
diff view generated by jsdifflib
1
In do_v7m_exception_exit(), we perform various checks as part of
1
From: Alex Bennée <alex.bennee@linaro.org>
2
performing the exception return. If one of these checks fails, the
3
architecture requires that we take an appropriate exception on the
4
existing stackframe. We implement this by calling
5
v7m_exception_taken() to set up to take the new exception, and then
6
immediately returning from do_v7m_exception_exit() without proceeding
7
any further with the unstack-and-exception-return process.
8
2
9
In a couple of checks that are new in v8.1M, we forgot the "return"
3
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
10
statement, with the effect that if bad code in the guest tripped over
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
these checks we would set up to take a UsageFault exception but then
12
blunder on trying to also unstack and return from the original
13
exception, with the probable result that the guest would crash.
14
15
Add the missing return statements.
16
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20250204125009.2281315-10-peter.maydell@linaro.org
19
Message-id: 20210723162146.5167-3-peter.maydell@linaro.org
7
Cc: qemu-stable@nongnu.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
9
---
21
target/arm/m_helper.c | 2 ++
10
hw/arm/sbsa-ref.c | 2 ++
22
1 file changed, 2 insertions(+)
11
1 file changed, 2 insertions(+)
23
12
24
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
13
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
25
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/m_helper.c
15
--- a/hw/arm/sbsa-ref.c
27
+++ b/target/arm/m_helper.c
16
+++ b/hw/arm/sbsa-ref.c
28
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
17
@@ -XXX,XX +XXX,XX @@ static void create_gic(SBSAMachineState *sms, MemoryRegion *mem)
29
qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
18
[GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
30
"stackframe: NSACR prevents clearing FPU registers\n");
19
[GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
31
v7m_exception_taken(cpu, excret, true, false);
20
[GTIMER_HYPVIRT] = ARCH_TIMER_NS_EL2_VIRT_IRQ,
32
+ return;
21
+ [GTIMER_S_EL2_PHYS] = ARCH_TIMER_S_EL2_IRQ,
33
} else if (!cpacr_pass) {
22
+ [GTIMER_S_EL2_VIRT] = ARCH_TIMER_S_EL2_VIRT_IRQ,
34
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
23
};
35
exc_secure);
24
36
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
25
for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
37
qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
38
"stackframe: CPACR prevents clearing FPU registers\n");
39
v7m_exception_taken(cpu, excret, true, false);
40
+ return;
41
}
42
}
43
/* Clear s0..s15, FPSCR and VPR */
44
--
26
--
45
2.20.1
27
2.43.0
46
28
47
29
diff view generated by jsdifflib
New patch
1
Our LDRD implementation is wrong in two respects:
1
2
3
* if the address is 4-aligned and the load crosses a page boundary
4
and the second load faults and the first load was to the
5
base register (as in cases like "ldrd r2, r3, [r2]", then we
6
must not update the base register before taking the fault
7
* if the address is 8-aligned the access must be a 64-bit
8
single-copy atomic access, not two 32-bit accesses
9
10
Rewrite the handling of the loads in LDRD to use a single
11
tcg_gen_qemu_ld_i64() and split the result into the destination
12
registers. This allows us to get the atomicity requirements
13
right, and also implicitly means that we won't update the
14
base register too early for the page-crossing case.
15
16
Note that because we no longer increment 'addr' by 4 in the course of
17
performing the LDRD we must change the adjustment value we pass to
18
op_addr_ri_post() and op_addr_rr_post(): it no longer needs to
19
subtract 4 to get the correct value to use if doing base register
20
writeback.
21
22
STRD has the same problem with not getting the atomicity right;
23
we will deal with that in the following commit.
24
25
Cc: qemu-stable@nongnu.org
26
Reported-by: Stu Grossman <stu.grossman@gmail.com>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
29
Message-id: 20250227142746.1698904-2-peter.maydell@linaro.org
30
---
31
target/arm/tcg/translate.c | 70 +++++++++++++++++++++++++-------------
32
1 file changed, 46 insertions(+), 24 deletions(-)
33
34
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/tcg/translate.c
37
+++ b/target/arm/tcg/translate.c
38
@@ -XXX,XX +XXX,XX @@ static bool op_store_rr(DisasContext *s, arg_ldst_rr *a,
39
return true;
40
}
41
42
+static void do_ldrd_load(DisasContext *s, TCGv_i32 addr, int rt, int rt2)
43
+{
44
+ /*
45
+ * LDRD is required to be an atomic 64-bit access if the
46
+ * address is 8-aligned, two atomic 32-bit accesses if
47
+ * it's only 4-aligned, and to give an alignment fault
48
+ * if it's not 4-aligned. This is MO_ALIGN_4 | MO_ATOM_SUBALIGN.
49
+ * Rt is always the word from the lower address, and Rt2 the
50
+ * data from the higher address, regardless of endianness.
51
+ * So (like gen_load_exclusive) we avoid gen_aa32_ld_i64()
52
+ * so we don't get its SCTLR_B check, and instead do a 64-bit access
53
+ * using MO_BE if appropriate and then split the two halves.
54
+ *
55
+ * For M-profile, and for A-profile before LPAE, the 64-bit
56
+ * atomicity is not required. We could model that using
57
+ * the looser MO_ATOM_IFALIGN_PAIR, but providing a higher
58
+ * level of atomicity than required is harmless (we would not
59
+ * currently generate better code for IFALIGN_PAIR here).
60
+ *
61
+ * This also gives us the correct behaviour of not updating
62
+ * rt if the load of rt2 faults; this is required for cases
63
+ * like "ldrd r2, r3, [r2]" where rt is also the base register.
64
+ */
65
+ int mem_idx = get_mem_index(s);
66
+ MemOp opc = MO_64 | MO_ALIGN_4 | MO_ATOM_SUBALIGN | s->be_data;
67
+ TCGv taddr = gen_aa32_addr(s, addr, opc);
68
+ TCGv_i64 t64 = tcg_temp_new_i64();
69
+ TCGv_i32 tmp = tcg_temp_new_i32();
70
+ TCGv_i32 tmp2 = tcg_temp_new_i32();
71
+
72
+ tcg_gen_qemu_ld_i64(t64, taddr, mem_idx, opc);
73
+ if (s->be_data == MO_BE) {
74
+ tcg_gen_extr_i64_i32(tmp2, tmp, t64);
75
+ } else {
76
+ tcg_gen_extr_i64_i32(tmp, tmp2, t64);
77
+ }
78
+ store_reg(s, rt, tmp);
79
+ store_reg(s, rt2, tmp2);
80
+}
81
+
82
static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
83
{
84
- int mem_idx = get_mem_index(s);
85
- TCGv_i32 addr, tmp;
86
+ TCGv_i32 addr;
87
88
if (!ENABLE_ARCH_5TE) {
89
return false;
90
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
91
}
92
addr = op_addr_rr_pre(s, a);
93
94
- tmp = tcg_temp_new_i32();
95
- gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
96
- store_reg(s, a->rt, tmp);
97
-
98
- tcg_gen_addi_i32(addr, addr, 4);
99
-
100
- tmp = tcg_temp_new_i32();
101
- gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
102
- store_reg(s, a->rt + 1, tmp);
103
+ do_ldrd_load(s, addr, a->rt, a->rt + 1);
104
105
/* LDRD w/ base writeback is undefined if the registers overlap. */
106
- op_addr_rr_post(s, a, addr, -4);
107
+ op_addr_rr_post(s, a, addr, 0);
108
return true;
109
}
110
111
@@ -XXX,XX +XXX,XX @@ static bool op_store_ri(DisasContext *s, arg_ldst_ri *a,
112
113
static bool op_ldrd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
114
{
115
- int mem_idx = get_mem_index(s);
116
- TCGv_i32 addr, tmp;
117
+ TCGv_i32 addr;
118
119
addr = op_addr_ri_pre(s, a);
120
121
- tmp = tcg_temp_new_i32();
122
- gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
123
- store_reg(s, a->rt, tmp);
124
-
125
- tcg_gen_addi_i32(addr, addr, 4);
126
-
127
- tmp = tcg_temp_new_i32();
128
- gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
129
- store_reg(s, rt2, tmp);
130
+ do_ldrd_load(s, addr, a->rt, rt2);
131
132
/* LDRD w/ base writeback is undefined if the registers overlap. */
133
- op_addr_ri_post(s, a, addr, -4);
134
+ op_addr_ri_post(s, a, addr, 0);
135
return true;
136
}
137
138
--
139
2.43.0
diff view generated by jsdifflib
New patch
1
Our STRD implementation doesn't correctly implement the requirement:
2
* if the address is 8-aligned the access must be a 64-bit
3
single-copy atomic access, not two 32-bit accesses
1
4
5
Rewrite the handling of STRD to use a single tcg_gen_qemu_st_i64()
6
of a value produced by concatenating the two 32 bit source registers.
7
This allows us to get the atomicity right.
8
9
As with the LDRD change, now that we don't update 'addr' in the
10
course of performing the store we need to adjust the offset
11
we pass to op_addr_ri_post() and op_addr_rr_post().
12
13
Cc: qemu-stable@nongnu.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20250227142746.1698904-3-peter.maydell@linaro.org
17
---
18
target/arm/tcg/translate.c | 59 +++++++++++++++++++++++++-------------
19
1 file changed, 39 insertions(+), 20 deletions(-)
20
21
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/tcg/translate.c
24
+++ b/target/arm/tcg/translate.c
25
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
26
return true;
27
}
28
29
+static void do_strd_store(DisasContext *s, TCGv_i32 addr, int rt, int rt2)
30
+{
31
+ /*
32
+ * STRD is required to be an atomic 64-bit access if the
33
+ * address is 8-aligned, two atomic 32-bit accesses if
34
+ * it's only 4-aligned, and to give an alignment fault
35
+ * if it's not 4-aligned.
36
+ * Rt is always the word from the lower address, and Rt2 the
37
+ * data from the higher address, regardless of endianness.
38
+ * So (like gen_store_exclusive) we avoid gen_aa32_ld_i64()
39
+ * so we don't get its SCTLR_B check, and instead do a 64-bit access
40
+ * using MO_BE if appropriate, using a value constructed
41
+ * by putting the two halves together in the right order.
42
+ *
43
+ * As with LDRD, the 64-bit atomicity is not required for
44
+ * M-profile, or for A-profile before LPAE, and we provide
45
+ * the higher guarantee always for simplicity.
46
+ */
47
+ int mem_idx = get_mem_index(s);
48
+ MemOp opc = MO_64 | MO_ALIGN_4 | MO_ATOM_SUBALIGN | s->be_data;
49
+ TCGv taddr = gen_aa32_addr(s, addr, opc);
50
+ TCGv_i32 t1 = load_reg(s, rt);
51
+ TCGv_i32 t2 = load_reg(s, rt2);
52
+ TCGv_i64 t64 = tcg_temp_new_i64();
53
+
54
+ if (s->be_data == MO_BE) {
55
+ tcg_gen_concat_i32_i64(t64, t2, t1);
56
+ } else {
57
+ tcg_gen_concat_i32_i64(t64, t1, t2);
58
+ }
59
+ tcg_gen_qemu_st_i64(t64, taddr, mem_idx, opc);
60
+}
61
+
62
static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
63
{
64
- int mem_idx = get_mem_index(s);
65
- TCGv_i32 addr, tmp;
66
+ TCGv_i32 addr;
67
68
if (!ENABLE_ARCH_5TE) {
69
return false;
70
@@ -XXX,XX +XXX,XX @@ static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
71
}
72
addr = op_addr_rr_pre(s, a);
73
74
- tmp = load_reg(s, a->rt);
75
- gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
76
+ do_strd_store(s, addr, a->rt, a->rt + 1);
77
78
- tcg_gen_addi_i32(addr, addr, 4);
79
-
80
- tmp = load_reg(s, a->rt + 1);
81
- gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
82
-
83
- op_addr_rr_post(s, a, addr, -4);
84
+ op_addr_rr_post(s, a, addr, 0);
85
return true;
86
}
87
88
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRD_ri_t32(DisasContext *s, arg_ldst_ri2 *a)
89
90
static bool op_strd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
91
{
92
- int mem_idx = get_mem_index(s);
93
- TCGv_i32 addr, tmp;
94
+ TCGv_i32 addr;
95
96
addr = op_addr_ri_pre(s, a);
97
98
- tmp = load_reg(s, a->rt);
99
- gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
100
+ do_strd_store(s, addr, a->rt, rt2);
101
102
- tcg_gen_addi_i32(addr, addr, 4);
103
-
104
- tmp = load_reg(s, rt2);
105
- gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
106
-
107
- op_addr_ri_post(s, a, addr, -4);
108
+ op_addr_ri_post(s, a, addr, 0);
109
return true;
110
}
111
112
--
113
2.43.0
diff view generated by jsdifflib
1
The VECTPENDING field in the ICSR is 9 bits wide, in bits [20:12] of
1
All the callers of op_addr_rr_post() and op_addr_ri_post() now pass in
2
the register. We were incorrectly masking it to 8 bits, so it would
2
zero for the address_offset, so we can remove that argument.
3
report the wrong value if the pending exception was greater than 256.
4
Fix the bug.
5
3
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210723162146.5167-6-peter.maydell@linaro.org
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Message-id: 20250227142746.1698904-4-peter.maydell@linaro.org
9
---
8
---
10
hw/intc/armv7m_nvic.c | 2 +-
9
target/arm/tcg/translate.c | 26 +++++++++++++-------------
11
1 file changed, 1 insertion(+), 1 deletion(-)
10
1 file changed, 13 insertions(+), 13 deletions(-)
12
11
13
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
12
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/intc/armv7m_nvic.c
14
--- a/target/arm/tcg/translate.c
16
+++ b/hw/intc/armv7m_nvic.c
15
+++ b/target/arm/tcg/translate.c
17
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
16
@@ -XXX,XX +XXX,XX @@ static TCGv_i32 op_addr_rr_pre(DisasContext *s, arg_ldst_rr *a)
18
/* VECTACTIVE */
17
}
19
val = cpu->env.v7m.exception;
18
20
/* VECTPENDING */
19
static void op_addr_rr_post(DisasContext *s, arg_ldst_rr *a,
21
- val |= (s->vectpending & 0xff) << 12;
20
- TCGv_i32 addr, int address_offset)
22
+ val |= (s->vectpending & 0x1ff) << 12;
21
+ TCGv_i32 addr)
23
/* ISRPENDING - set if any external IRQ is pending */
22
{
24
if (nvic_isrpending(s)) {
23
if (!a->p) {
25
val |= (1 << 22);
24
TCGv_i32 ofs = load_reg(s, a->rm);
25
@@ -XXX,XX +XXX,XX @@ static void op_addr_rr_post(DisasContext *s, arg_ldst_rr *a,
26
} else if (!a->w) {
27
return;
28
}
29
- tcg_gen_addi_i32(addr, addr, address_offset);
30
store_reg(s, a->rn, addr);
31
}
32
33
@@ -XXX,XX +XXX,XX @@ static bool op_load_rr(DisasContext *s, arg_ldst_rr *a,
34
* Perform base writeback before the loaded value to
35
* ensure correct behavior with overlapping index registers.
36
*/
37
- op_addr_rr_post(s, a, addr, 0);
38
+ op_addr_rr_post(s, a, addr);
39
store_reg_from_load(s, a->rt, tmp);
40
return true;
41
}
42
@@ -XXX,XX +XXX,XX @@ static bool op_store_rr(DisasContext *s, arg_ldst_rr *a,
43
gen_aa32_st_i32(s, tmp, addr, mem_idx, mop);
44
disas_set_da_iss(s, mop, issinfo);
45
46
- op_addr_rr_post(s, a, addr, 0);
47
+ op_addr_rr_post(s, a, addr);
48
return true;
49
}
50
51
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
52
do_ldrd_load(s, addr, a->rt, a->rt + 1);
53
54
/* LDRD w/ base writeback is undefined if the registers overlap. */
55
- op_addr_rr_post(s, a, addr, 0);
56
+ op_addr_rr_post(s, a, addr);
57
return true;
58
}
59
60
@@ -XXX,XX +XXX,XX @@ static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
61
62
do_strd_store(s, addr, a->rt, a->rt + 1);
63
64
- op_addr_rr_post(s, a, addr, 0);
65
+ op_addr_rr_post(s, a, addr);
66
return true;
67
}
68
69
@@ -XXX,XX +XXX,XX @@ static TCGv_i32 op_addr_ri_pre(DisasContext *s, arg_ldst_ri *a)
70
}
71
72
static void op_addr_ri_post(DisasContext *s, arg_ldst_ri *a,
73
- TCGv_i32 addr, int address_offset)
74
+ TCGv_i32 addr)
75
{
76
+ int address_offset = 0;
77
if (!a->p) {
78
if (a->u) {
79
- address_offset += a->imm;
80
+ address_offset = a->imm;
81
} else {
82
- address_offset -= a->imm;
83
+ address_offset = -a->imm;
84
}
85
} else if (!a->w) {
86
return;
87
@@ -XXX,XX +XXX,XX @@ static bool op_load_ri(DisasContext *s, arg_ldst_ri *a,
88
* Perform base writeback before the loaded value to
89
* ensure correct behavior with overlapping index registers.
90
*/
91
- op_addr_ri_post(s, a, addr, 0);
92
+ op_addr_ri_post(s, a, addr);
93
store_reg_from_load(s, a->rt, tmp);
94
return true;
95
}
96
@@ -XXX,XX +XXX,XX @@ static bool op_store_ri(DisasContext *s, arg_ldst_ri *a,
97
gen_aa32_st_i32(s, tmp, addr, mem_idx, mop);
98
disas_set_da_iss(s, mop, issinfo);
99
100
- op_addr_ri_post(s, a, addr, 0);
101
+ op_addr_ri_post(s, a, addr);
102
return true;
103
}
104
105
@@ -XXX,XX +XXX,XX @@ static bool op_ldrd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
106
do_ldrd_load(s, addr, a->rt, rt2);
107
108
/* LDRD w/ base writeback is undefined if the registers overlap. */
109
- op_addr_ri_post(s, a, addr, 0);
110
+ op_addr_ri_post(s, a, addr);
111
return true;
112
}
113
114
@@ -XXX,XX +XXX,XX @@ static bool op_strd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
115
116
do_strd_store(s, addr, a->rt, rt2);
117
118
- op_addr_ri_post(s, a, addr, 0);
119
+ op_addr_ri_post(s, a, addr);
120
return true;
121
}
122
26
--
123
--
27
2.20.1
124
2.43.0
28
125
29
126
diff view generated by jsdifflib
New patch
1
In debug_helper.c we provide a few dummy versions of
2
debug registers:
3
* DBGVCR (AArch32 only): enable bits for vector-catch
4
debug events
5
* MDCCINT_EL1: interrupt enable bits for the DCC
6
debug communications channel
7
* DBGVCR32_EL2: the AArch64 accessor for the state in
8
DBGVCR
1
9
10
We implemented these only to stop Linux crashing on startup,
11
but we chose to implement them as ARM_CP_NOP. This worked
12
for Linux where it only cares about trying to write to these
13
registers, but is very confusing behaviour for anything that
14
wants to read the registers (perhaps for context state switches),
15
because the destination register will be left with whatever
16
random value it happened to have before the read.
17
18
Model these registers instead as RAZ.
19
20
Fixes: 5e8b12ffbb8c68 ("target-arm: Implement minimal DBGVCR, OSDLR_EL1, MDCCSR_EL0")
21
Fixes: 5dbdc4342f479d ("target-arm: Implement dummy MDCCINT_EL1")
22
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2708
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Message-id: 20250228162424.1917269-1-peter.maydell@linaro.org
26
---
27
target/arm/debug_helper.c | 7 ++++---
28
1 file changed, 4 insertions(+), 3 deletions(-)
29
30
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/debug_helper.c
33
+++ b/target/arm/debug_helper.c
34
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
35
{ .name = "DBGVCR",
36
.cp = 14, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,
37
.access = PL1_RW, .accessfn = access_tda,
38
- .type = ARM_CP_NOP },
39
+ .type = ARM_CP_CONST, .resetvalue = 0 },
40
/*
41
* Dummy MDCCINT_EL1, since we don't implement the Debug Communications
42
* Channel but Linux may try to access this register. The 32-bit
43
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
44
{ .name = "MDCCINT_EL1", .state = ARM_CP_STATE_BOTH,
45
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
46
.access = PL1_RW, .accessfn = access_tdcc,
47
- .type = ARM_CP_NOP },
48
+ .type = ARM_CP_CONST, .resetvalue = 0 },
49
/*
50
* Dummy DBGCLAIM registers.
51
* "The architecture does not define any functionality for the CLAIM tag bits.",
52
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_aa32_el1_reginfo[] = {
53
{ .name = "DBGVCR32_EL2", .state = ARM_CP_STATE_AA64,
54
.opc0 = 2, .opc1 = 4, .crn = 0, .crm = 7, .opc2 = 0,
55
.access = PL2_RW, .accessfn = access_dbgvcr32,
56
- .type = ARM_CP_NOP | ARM_CP_EL3_NO_EL2_KEEP },
57
+ .type = ARM_CP_CONST | ARM_CP_EL3_NO_EL2_KEEP,
58
+ .resetvalue = 0 },
59
};
60
61
static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
62
--
63
2.43.0
diff view generated by jsdifflib
1
For M-profile, we weren't reporting alignment faults triggered by the
1
Currently we call icount_start_warp_timer() from timerlist_rearm().
2
generic TCG code correctly to the guest. These get passed into
2
This produces incorrect behaviour, because timerlist_rearm() is
3
arm_v7m_cpu_do_interrupt() as an EXCP_DATA_ABORT with an A-profile
3
called, for instance, when a timer callback modifies its timer. We
4
style exception.fsr value of 1. We didn't check for this, and so
4
cannot decide here to warp the timer forwards to the next timer
5
they fell through into the default of "assume this is an MPU fault"
5
deadline merely because all_cpu_threads_idle() is true, because the
6
and were reported to the guest as a data access violation MPU fault.
6
timer callback we were called from (or some other callback later in
7
the list of callbacks being invoked) may be about to raise a CPU
8
interrupt and move a CPU from idle to ready.
7
9
8
Report these alignment faults as UsageFaults which set the UNALIGNED
10
The only valid place to choose to warp the timer forward is from the
9
bit in the UFSR.
11
main loop, when we know we have no outstanding IO or timer callbacks
12
that might be about to wake up a CPU.
10
13
14
For Arm guests, this bug was mostly latent until the refactoring
15
commit f6fc36deef6abc ("target/arm/helper: Implement
16
CNTHCTL_EL2.CNT[VP]MASK"), which exposed it because it refactored a
17
timer callback so that it happened to call timer_mod() first and
18
raise the interrupt second, when it had previously raised the
19
interrupt first and called timer_mod() afterwards.
20
21
This call seems to have originally derived from the
22
pre-record-and-replay icount code, which (as of e.g. commit
23
db1a49726c3c in 2010) in this location did a call to
24
qemu_notify_event(), necessary to get the icount code in the vCPU
25
round-robin thread to stop and recalculate the icount deadline when a
26
timer was reprogrammed from the IO thread. In current QEMU,
27
everything is done on the vCPU thread when we are in icount mode, so
28
there's no need to try to notify another thread here.
29
30
I suspect that the other reason why this call was doing icount timer
31
warping is that it pre-dates commit efab87cf79077a from 2015, which
32
added a call to icount_start_warp_timer() to main_loop_wait(). Once
33
the call in timerlist_rearm() has been removed, if the timer
34
callbacks don't cause any CPU to be woken up then we will end up
35
calling icount_start_warp_timer() from main_loop_wait() when the rr
36
main loop code calls rr_wait_io_event().
37
38
Remove the incorrect call from timerlist_rearm().
39
40
Cc: qemu-stable@nongnu.org
41
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2703
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
42
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
43
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20210723162146.5167-4-peter.maydell@linaro.org
44
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
45
Tested-by: Alex Bennée <alex.bennee@linaro.org>
46
Message-id: 20250210135804.3526943-1-peter.maydell@linaro.org
14
---
47
---
15
target/arm/m_helper.c | 8 ++++++++
48
util/qemu-timer.c | 4 ----
16
1 file changed, 8 insertions(+)
49
1 file changed, 4 deletions(-)
17
50
18
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
51
diff --git a/util/qemu-timer.c b/util/qemu-timer.c
19
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/m_helper.c
53
--- a/util/qemu-timer.c
21
+++ b/target/arm/m_helper.c
54
+++ b/util/qemu-timer.c
22
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
55
@@ -XXX,XX +XXX,XX @@ static bool timer_mod_ns_locked(QEMUTimerList *timer_list,
23
env->v7m.sfsr |= R_V7M_SFSR_LSERR_MASK;
56
24
break;
57
static void timerlist_rearm(QEMUTimerList *timer_list)
25
case EXCP_UNALIGNED:
58
{
26
+ /* Unaligned faults reported by M-profile aware code */
59
- /* Interrupt execution to force deadline recalculation. */
27
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
60
- if (icount_enabled() && timer_list->clock->type == QEMU_CLOCK_VIRTUAL) {
28
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_UNALIGNED_MASK;
61
- icount_start_warp_timer();
29
break;
62
- }
30
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
63
timerlist_notify(timer_list);
31
}
64
}
32
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_BUS, false);
65
33
break;
34
+ case 0x1: /* Alignment fault reported by generic code */
35
+ qemu_log_mask(CPU_LOG_INT,
36
+ "...really UsageFault with UFSR.UNALIGNED\n");
37
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_UNALIGNED_MASK;
38
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
39
+ env->v7m.secure);
40
+ break;
41
default:
42
/*
43
* All other FSR values are either MPU faults or "can't happen
44
--
66
--
45
2.20.1
67
2.43.0
46
68
47
69
diff view generated by jsdifflib
1
For M-profile, unlike A-profile, the low 2 bits of SP are defined to be
1
Expand the example in the comment documenting MO_ATOM_SUBALIGN,
2
RES0H, which is to say that they must be hardwired to zero so that
2
to be clearer about the atomicity guarantees it represents.
3
guest attempts to write non-zero values to them are ignored.
4
5
Implement this behaviour by masking out the low bits:
6
* for writes to r13 by the gdbstub
7
* for writes to any of the various flavours of SP via MSR
8
* for writes to r13 via store_reg() in generated code
9
10
Note that all the direct uses of cpu_R[] in translate.c are in places
11
where the register is definitely not r13 (usually because that has
12
been checked for as an UNDEFINED or UNPREDICTABLE case and handled as
13
UNDEF).
14
15
All the other writes to regs[13] in C code are either:
16
* A-profile only code
17
* writes of values we can guarantee to be aligned, such as
18
- writes of previous-SP-value plus or minus a 4-aligned constant
19
- writes of the value in an SP limit register (which we already
20
enforce to be aligned)
21
3
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 20210723162146.5167-2-peter.maydell@linaro.org
6
Message-id: 20250228103222.1838913-1-peter.maydell@linaro.org
25
---
7
---
26
target/arm/gdbstub.c | 4 ++++
8
include/exec/memop.h | 8 ++++++--
27
target/arm/m_helper.c | 14 ++++++++------
9
1 file changed, 6 insertions(+), 2 deletions(-)
28
target/arm/translate.c | 3 +++
29
3 files changed, 15 insertions(+), 6 deletions(-)
30
10
31
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
11
diff --git a/include/exec/memop.h b/include/exec/memop.h
32
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/gdbstub.c
13
--- a/include/exec/memop.h
34
+++ b/target/arm/gdbstub.c
14
+++ b/include/exec/memop.h
35
@@ -XXX,XX +XXX,XX @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
15
@@ -XXX,XX +XXX,XX @@ typedef enum MemOp {
36
16
* Depending on alignment, one or both will be single-copy atomic.
37
if (n < 16) {
17
* This is the atomicity e.g. of Arm FEAT_LSE2 LDP.
38
/* Core integer register. */
18
* MO_ATOM_SUBALIGN: the operation is single-copy atomic by parts
39
+ if (n == 13 && arm_feature(env, ARM_FEATURE_M)) {
19
- * by the alignment. E.g. if the address is 0 mod 4, then each
40
+ /* M profile SP low bits are always 0 */
20
- * 4-byte subobject is single-copy atomic.
41
+ tmp &= ~3;
21
+ * by the alignment. E.g. if an 8-byte value is accessed at an
42
+ }
22
+ * address which is 0 mod 8, then the whole 8-byte access is
43
env->regs[n] = tmp;
23
+ * single-copy atomic; otherwise, if it is accessed at 0 mod 4
44
return 4;
24
+ * then each 4-byte subobject is single-copy atomic; otherwise
45
}
25
+ * if it is accessed at 0 mod 2 then the four 2-byte subobjects
46
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
26
+ * are single-copy atomic.
47
index XXXXXXX..XXXXXXX 100644
27
* This is the atomicity e.g. of IBM Power.
48
--- a/target/arm/m_helper.c
28
* MO_ATOM_NONE: the operation has no atomicity requirements.
49
+++ b/target/arm/m_helper.c
29
*
50
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
51
if (!env->v7m.secure) {
52
return;
53
}
54
- env->v7m.other_ss_msp = val;
55
+ env->v7m.other_ss_msp = val & ~3;
56
return;
57
case 0x89: /* PSP_NS */
58
if (!env->v7m.secure) {
59
return;
60
}
61
- env->v7m.other_ss_psp = val;
62
+ env->v7m.other_ss_psp = val & ~3;
63
return;
64
case 0x8a: /* MSPLIM_NS */
65
if (!env->v7m.secure) {
66
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
67
68
limit = is_psp ? env->v7m.psplim[false] : env->v7m.msplim[false];
69
70
+ val &= ~0x3;
71
+
72
if (val < limit) {
73
raise_exception_ra(env, EXCP_STKOF, 0, 1, GETPC());
74
}
75
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
76
break;
77
case 8: /* MSP */
78
if (v7m_using_psp(env)) {
79
- env->v7m.other_sp = val;
80
+ env->v7m.other_sp = val & ~3;
81
} else {
82
- env->regs[13] = val;
83
+ env->regs[13] = val & ~3;
84
}
85
break;
86
case 9: /* PSP */
87
if (v7m_using_psp(env)) {
88
- env->regs[13] = val;
89
+ env->regs[13] = val & ~3;
90
} else {
91
- env->v7m.other_sp = val;
92
+ env->v7m.other_sp = val & ~3;
93
}
94
break;
95
case 10: /* MSPLIM */
96
diff --git a/target/arm/translate.c b/target/arm/translate.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/target/arm/translate.c
99
+++ b/target/arm/translate.c
100
@@ -XXX,XX +XXX,XX @@ void store_reg(DisasContext *s, int reg, TCGv_i32 var)
101
*/
102
tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
103
s->base.is_jmp = DISAS_JUMP;
104
+ } else if (reg == 13 && arm_dc_feature(s, ARM_FEATURE_M)) {
105
+ /* For M-profile SP bits [1:0] are always zero */
106
+ tcg_gen_andi_i32(var, var, ~3);
107
}
108
tcg_gen_mov_i32(cpu_R[reg], var);
109
tcg_temp_free_i32(var);
110
--
30
--
111
2.20.1
31
2.43.0
112
113
diff view generated by jsdifflib
New patch
1
From: JianChunfu <jansef.jian@hj-micro.com>
1
2
3
Use a similar terminology smmu_hash_remove_by_sid_range() as the one
4
being used for other hash table matching functions since
5
smmuv3_invalidate_ste() name is not self explanatory, and introduce a
6
helper that invokes the g_hash_table_foreach_remove.
7
8
No functional change intended.
9
10
Signed-off-by: JianChunfu <jansef.jian@hj-micro.com>
11
Reviewed-by: Eric Auger <eric.auger@redhat.com>
12
Message-id: 20250228031438.3916-1-jansef.jian@hj-micro.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/arm/smmu-internal.h | 5 -----
16
include/hw/arm/smmu-common.h | 6 ++++++
17
hw/arm/smmu-common.c | 21 +++++++++++++++++++++
18
hw/arm/smmuv3.c | 19 ++-----------------
19
hw/arm/trace-events | 3 ++-
20
5 files changed, 31 insertions(+), 23 deletions(-)
21
22
diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/arm/smmu-internal.h
25
+++ b/hw/arm/smmu-internal.h
26
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUIOTLBPageInvInfo {
27
uint64_t mask;
28
} SMMUIOTLBPageInvInfo;
29
30
-typedef struct SMMUSIDRange {
31
- uint32_t start;
32
- uint32_t end;
33
-} SMMUSIDRange;
34
-
35
#endif
36
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/arm/smmu-common.h
39
+++ b/include/hw/arm/smmu-common.h
40
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUIOTLBKey {
41
uint8_t level;
42
} SMMUIOTLBKey;
43
44
+typedef struct SMMUSIDRange {
45
+ uint32_t start;
46
+ uint32_t end;
47
+} SMMUSIDRange;
48
+
49
struct SMMUState {
50
/* <private> */
51
SysBusDevice dev;
52
@@ -XXX,XX +XXX,XX @@ void smmu_iotlb_inv_iova(SMMUState *s, int asid, int vmid, dma_addr_t iova,
53
uint8_t tg, uint64_t num_pages, uint8_t ttl);
54
void smmu_iotlb_inv_ipa(SMMUState *s, int vmid, dma_addr_t ipa, uint8_t tg,
55
uint64_t num_pages, uint8_t ttl);
56
+void smmu_configs_inv_sid_range(SMMUState *s, SMMUSIDRange sid_range);
57
/* Unmap the range of all the notifiers registered to any IOMMU mr */
58
void smmu_inv_notifiers_all(SMMUState *s);
59
60
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/arm/smmu-common.c
63
+++ b/hw/arm/smmu-common.c
64
@@ -XXX,XX +XXX,XX @@ static gboolean smmu_hash_remove_by_vmid_ipa(gpointer key, gpointer value,
65
((entry->iova & ~info->mask) == info->iova);
66
}
67
68
+static gboolean
69
+smmu_hash_remove_by_sid_range(gpointer key, gpointer value, gpointer user_data)
70
+{
71
+ SMMUDevice *sdev = (SMMUDevice *)key;
72
+ uint32_t sid = smmu_get_sid(sdev);
73
+ SMMUSIDRange *sid_range = (SMMUSIDRange *)user_data;
74
+
75
+ if (sid < sid_range->start || sid > sid_range->end) {
76
+ return false;
77
+ }
78
+ trace_smmu_config_cache_inv(sid);
79
+ return true;
80
+}
81
+
82
+void smmu_configs_inv_sid_range(SMMUState *s, SMMUSIDRange sid_range)
83
+{
84
+ trace_smmu_configs_inv_sid_range(sid_range.start, sid_range.end);
85
+ g_hash_table_foreach_remove(s->configs, smmu_hash_remove_by_sid_range,
86
+ &sid_range);
87
+}
88
+
89
void smmu_iotlb_inv_iova(SMMUState *s, int asid, int vmid, dma_addr_t iova,
90
uint8_t tg, uint64_t num_pages, uint8_t ttl)
91
{
92
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/hw/arm/smmuv3.c
95
+++ b/hw/arm/smmuv3.c
96
@@ -XXX,XX +XXX,XX @@ static void smmuv3_flush_config(SMMUDevice *sdev)
97
SMMUv3State *s = sdev->smmu;
98
SMMUState *bc = &s->smmu_state;
99
100
- trace_smmuv3_config_cache_inv(smmu_get_sid(sdev));
101
+ trace_smmu_config_cache_inv(smmu_get_sid(sdev));
102
g_hash_table_remove(bc->configs, sdev);
103
}
104
105
@@ -XXX,XX +XXX,XX @@ static void smmuv3_range_inval(SMMUState *s, Cmd *cmd, SMMUStage stage)
106
}
107
}
108
109
-static gboolean
110
-smmuv3_invalidate_ste(gpointer key, gpointer value, gpointer user_data)
111
-{
112
- SMMUDevice *sdev = (SMMUDevice *)key;
113
- uint32_t sid = smmu_get_sid(sdev);
114
- SMMUSIDRange *sid_range = (SMMUSIDRange *)user_data;
115
-
116
- if (sid < sid_range->start || sid > sid_range->end) {
117
- return false;
118
- }
119
- trace_smmuv3_config_cache_inv(sid);
120
- return true;
121
-}
122
-
123
static int smmuv3_cmdq_consume(SMMUv3State *s)
124
{
125
SMMUState *bs = ARM_SMMU(s);
126
@@ -XXX,XX +XXX,XX @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
127
sid_range.end = sid_range.start + mask;
128
129
trace_smmuv3_cmdq_cfgi_ste_range(sid_range.start, sid_range.end);
130
- g_hash_table_foreach_remove(bs->configs, smmuv3_invalidate_ste,
131
- &sid_range);
132
+ smmu_configs_inv_sid_range(bs, sid_range);
133
break;
134
}
135
case SMMU_CMD_CFGI_CD:
136
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
137
index XXXXXXX..XXXXXXX 100644
138
--- a/hw/arm/trace-events
139
+++ b/hw/arm/trace-events
140
@@ -XXX,XX +XXX,XX @@ smmu_iotlb_inv_asid_vmid(int asid, int vmid) "IOTLB invalidate asid=%d vmid=%d"
141
smmu_iotlb_inv_vmid(int vmid) "IOTLB invalidate vmid=%d"
142
smmu_iotlb_inv_vmid_s1(int vmid) "IOTLB invalidate vmid=%d"
143
smmu_iotlb_inv_iova(int asid, uint64_t addr) "IOTLB invalidate asid=%d addr=0x%"PRIx64
144
+smmu_configs_inv_sid_range(uint32_t start, uint32_t end) "Config cache INV SID range from 0x%x to 0x%x"
145
+smmu_config_cache_inv(uint32_t sid) "Config cache INV for sid=0x%x"
146
smmu_inv_notifiers_mr(const char *name) "iommu mr=%s"
147
smmu_iotlb_lookup_hit(int asid, int vmid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache HIT asid=%d vmid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d"
148
smmu_iotlb_lookup_miss(int asid, int vmid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache MISS asid=%d vmid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d"
149
@@ -XXX,XX +XXX,XX @@ smmuv3_cmdq_tlbi_nh(int vmid) "vmid=%d"
150
smmuv3_cmdq_tlbi_nsnh(void) ""
151
smmuv3_cmdq_tlbi_nh_asid(int asid) "asid=%d"
152
smmuv3_cmdq_tlbi_s12_vmid(int vmid) "vmid=%d"
153
-smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid=0x%x"
154
smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s"
155
smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s"
156
smmuv3_inv_notifiers_iova(const char *name, int asid, int vmid, uint64_t iova, uint8_t tg, uint64_t num_pages, int stage) "iommu mr=%s asid=%d vmid=%d iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" stage=%d"
157
--
158
2.43.0
diff view generated by jsdifflib
New patch
1
From: Keith Packard <keithp@keithp.com>
1
2
3
The documentation says the vector is at 0xffffff80, instead of the
4
previous value of 0xffffffc0. That value must have been a bug because
5
the standard vector values (20, 21, 23, 25, 30) were all
6
past the end of the array.
7
8
Signed-off-by: Keith Packard <keithp@keithp.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/rx/helper.c | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
14
15
diff --git a/target/rx/helper.c b/target/rx/helper.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/rx/helper.c
18
+++ b/target/rx/helper.c
19
@@ -XXX,XX +XXX,XX @@ void rx_cpu_do_interrupt(CPUState *cs)
20
cpu_stl_data(env, env->isp, env->pc);
21
22
if (vec < 0x100) {
23
- env->pc = cpu_ldl_data(env, 0xffffffc0 + vec * 4);
24
+ env->pc = cpu_ldl_data(env, 0xffffff80 + vec * 4);
25
} else {
26
env->pc = cpu_ldl_data(env, env->intb + (vec & 0xff) * 4);
27
}
28
--
29
2.43.0
diff view generated by jsdifflib
New patch
1
From: Keith Packard <keithp@keithp.com>
1
2
3
Functions which modify TCG globals must not be marked TCG_CALL_NO_WG,
4
as that tells the optimizer that TCG global values already loaded in
5
machine registers are still valid, and so any changes which these
6
helpers make to the CPU state may be ignored.
7
8
The target/rx code chooses to put (among other things) all the PSW
9
bits and also ACC into globals, so the NO_WG flag on various
10
functions that touch the PSW or ACC is incorrect and must be removed.
11
This includes all the floating point helper functions, because
12
update_fpsw() will update PSW Z and S.
13
14
Signed-off-by: Keith Packard <keithp@keithp.com>
15
[PMM: Clarified commit message]
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
target/rx/helper.h | 34 +++++++++++++++++-----------------
20
1 file changed, 17 insertions(+), 17 deletions(-)
21
22
diff --git a/target/rx/helper.h b/target/rx/helper.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/rx/helper.h
25
+++ b/target/rx/helper.h
26
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_1(raise_privilege_violation, noreturn, env)
27
DEF_HELPER_1(wait, noreturn, env)
28
DEF_HELPER_2(rxint, noreturn, env, i32)
29
DEF_HELPER_1(rxbrk, noreturn, env)
30
-DEF_HELPER_FLAGS_3(fadd, TCG_CALL_NO_WG, f32, env, f32, f32)
31
-DEF_HELPER_FLAGS_3(fsub, TCG_CALL_NO_WG, f32, env, f32, f32)
32
-DEF_HELPER_FLAGS_3(fmul, TCG_CALL_NO_WG, f32, env, f32, f32)
33
-DEF_HELPER_FLAGS_3(fdiv, TCG_CALL_NO_WG, f32, env, f32, f32)
34
-DEF_HELPER_FLAGS_3(fcmp, TCG_CALL_NO_WG, void, env, f32, f32)
35
-DEF_HELPER_FLAGS_2(ftoi, TCG_CALL_NO_WG, i32, env, f32)
36
-DEF_HELPER_FLAGS_2(round, TCG_CALL_NO_WG, i32, env, f32)
37
-DEF_HELPER_FLAGS_2(itof, TCG_CALL_NO_WG, f32, env, i32)
38
+DEF_HELPER_3(fadd, f32, env, f32, f32)
39
+DEF_HELPER_3(fsub, f32, env, f32, f32)
40
+DEF_HELPER_3(fmul, f32, env, f32, f32)
41
+DEF_HELPER_3(fdiv, f32, env, f32, f32)
42
+DEF_HELPER_3(fcmp, void, env, f32, f32)
43
+DEF_HELPER_2(ftoi, i32, env, f32)
44
+DEF_HELPER_2(round, i32, env, f32)
45
+DEF_HELPER_2(itof, f32, env, i32)
46
DEF_HELPER_2(set_fpsw, void, env, i32)
47
-DEF_HELPER_FLAGS_2(racw, TCG_CALL_NO_WG, void, env, i32)
48
-DEF_HELPER_FLAGS_2(set_psw_rte, TCG_CALL_NO_WG, void, env, i32)
49
-DEF_HELPER_FLAGS_2(set_psw, TCG_CALL_NO_WG, void, env, i32)
50
+DEF_HELPER_2(racw, void, env, i32)
51
+DEF_HELPER_2(set_psw_rte, void, env, i32)
52
+DEF_HELPER_2(set_psw, void, env, i32)
53
DEF_HELPER_1(pack_psw, i32, env)
54
-DEF_HELPER_FLAGS_3(div, TCG_CALL_NO_WG, i32, env, i32, i32)
55
-DEF_HELPER_FLAGS_3(divu, TCG_CALL_NO_WG, i32, env, i32, i32)
56
-DEF_HELPER_FLAGS_1(scmpu, TCG_CALL_NO_WG, void, env)
57
+DEF_HELPER_3(div, i32, env, i32, i32)
58
+DEF_HELPER_3(divu, i32, env, i32, i32)
59
+DEF_HELPER_1(scmpu, void, env)
60
DEF_HELPER_1(smovu, void, env)
61
DEF_HELPER_1(smovf, void, env)
62
DEF_HELPER_1(smovb, void, env)
63
DEF_HELPER_2(sstr, void, env, i32)
64
-DEF_HELPER_FLAGS_2(swhile, TCG_CALL_NO_WG, void, env, i32)
65
-DEF_HELPER_FLAGS_2(suntil, TCG_CALL_NO_WG, void, env, i32)
66
-DEF_HELPER_FLAGS_2(rmpa, TCG_CALL_NO_WG, void, env, i32)
67
+DEF_HELPER_2(swhile, void, env, i32)
68
+DEF_HELPER_2(suntil, void, env, i32)
69
+DEF_HELPER_2(rmpa, void, env, i32)
70
DEF_HELPER_1(satr, void, env)
71
--
72
2.43.0
diff view generated by jsdifflib