1
Arm patch queue -- these are all bug fix patches but we might
1
Hi; here's a target-arm pullreq to go in before softfreeze.
2
as well put them in to rc0...
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 2c8cfc0b52b5a4d123c26c0b5fdf941be24805be:
9
The following changes since commit 98c7362b1efe651327385a25874a73e008c6549e:
8
10
9
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (2018-03-19 11:44:26 +0000)
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
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180319
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 ff72cb6b46b95bb530787add5277c211af3d31c6:
17
for you to fetch changes up to 0ce0739d46983e5e88fa9c149cb305689c9d8c6f:
16
18
17
hw/arm/raspi: Provide spin-loop code for AArch64 CPUs (2018-03-19 18:23:24 +0000)
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
* fsl-imx6: Fix incorrect Ethernet interrupt defines
23
* hw/arm/smmu-common: Remove the repeated ttb field
22
* dump: Update correct kdump phys_base field for AArch64
24
* hw/gpio: npcm7xx: fixup out-of-bounds access
23
* char: i.MX: Add support for "TX complete" interrupt
25
* tests/functional/test_arm_sx1: Check whether the serial console is working
24
* bcm2836/raspi: Fix various bugs resulting in panics trying
26
* target/arm: Fix minor bugs in generic timer register handling
25
to boot a Debian Linux kernel on raspi3
27
* target/arm: Implement SEL2 physical and virtual timers
28
* target/arm: Correct STRD, LDRD atomicity and fault behaviour
29
* target/arm: Make dummy debug registers RAZ, not NOP
30
* util/qemu-timer.c: Don't warp timer from timerlist_rearm()
31
* include/exec/memop.h: Expand comment for MO_ATOM_SUBALIGN
32
* hw/arm/smmu: Introduce smmu_configs_inv_sid_range() helper
33
* target/rx: Set exception vector base to 0xffffff80
34
* target/rx: Remove TCG_CALL_NO_WG from helpers which write env
26
35
27
----------------------------------------------------------------
36
----------------------------------------------------------------
28
Andrey Smirnov (2):
37
Alex Bennée (4):
29
char: i.MX: Simplify imx_update()
38
target/arm: Implement SEL2 physical and virtual timers
30
char: i.MX: Add support for "TX complete" interrupt
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
31
42
32
Guenter Roeck (1):
43
JianChunfu (2):
33
fsl-imx6: Swap Ethernet interrupt defines
44
hw/arm/smmu-common: Remove the repeated ttb field
45
hw/arm/smmu: Introduce smmu_configs_inv_sid_range() helper
34
46
35
Peter Maydell (9):
47
Keith Packard (2):
36
hw/arm/raspi: Don't do board-setup or secure-boot for raspi3
48
target/rx: Set exception vector base to 0xffffff80
37
hw/arm/boot: assert that secure_boot and secure_board_setup are false for AArch64
49
target/rx: Remove TCG_CALL_NO_WG from helpers which write env
38
hw/arm/boot: If booting a kernel in EL2, set SCR_EL3.HCE
39
hw/arm/bcm2386: Fix parent type of bcm2386
40
hw/arm/bcm2836: Rename bcm2836 type/struct to bcm283x
41
hw/arm/bcm2836: Create proper bcm2837 device
42
hw/arm/bcm2836: Use correct affinity values for BCM2837
43
hw/arm/bcm2836: Hardcode correct CPU type
44
hw/arm/raspi: Provide spin-loop code for AArch64 CPUs
45
50
46
Wei Huang (1):
51
Patrick Venture (1):
47
dump: Update correct kdump phys_base field for AArch64
52
hw/gpio: npcm7xx: fixup out-of-bounds access
48
53
49
include/hw/arm/bcm2836.h | 31 +++++++++++++---
54
Peter Maydell (11):
50
include/hw/arm/fsl-imx6.h | 4 +-
55
target/arm: Apply correct timer offset when calculating deadlines
51
include/hw/char/imx_serial.h | 3 ++
56
target/arm: Don't apply CNTVOFF_EL2 for EL2_VIRT timer
52
dump.c | 14 +++++--
57
target/arm: Make CNTPS_* UNDEF from Secure EL1 when Secure EL2 is enabled
53
hw/arm/bcm2836.c | 87 +++++++++++++++++++++++++++++++-------------
58
target/arm: Always apply CNTVOFF_EL2 for CNTV_TVAL_EL02 accesses
54
hw/arm/boot.c | 12 ++++++
59
target/arm: Refactor handling of timer offset for direct register accesses
55
hw/arm/raspi.c | 77 +++++++++++++++++++++++++++++++--------
60
target/arm: Correct LDRD atomicity and fault behaviour
56
hw/char/imx_serial.c | 44 ++++++++++++++++------
61
target/arm: Correct STRD atomicity
57
hw/net/imx_fec.c | 28 +++++++++++++-
62
target/arm: Drop unused address_offset from op_addr_{rr, ri}_post()
58
9 files changed, 237 insertions(+), 63 deletions(-)
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
59
66
67
Thomas Huth (1):
68
tests/functional/test_arm_sx1: Check whether the serial console is working
69
70
MAINTAINERS | 1 +
71
hw/arm/smmu-internal.h | 5 -
72
include/exec/memop.h | 8 +-
73
include/hw/arm/bsa.h | 2 +
74
include/hw/arm/smmu-common.h | 7 +-
75
target/arm/cpu.h | 2 +
76
target/arm/gtimer.h | 14 +-
77
target/arm/internals.h | 5 +-
78
target/rx/helper.h | 34 ++--
79
hw/arm/sbsa-ref.c | 2 +
80
hw/arm/smmu-common.c | 21 +++
81
hw/arm/smmuv3.c | 19 +--
82
hw/arm/virt.c | 2 +
83
hw/gpio/npcm7xx_gpio.c | 3 +-
84
target/arm/cpu.c | 4 +
85
target/arm/debug_helper.c | 7 +-
86
target/arm/helper.c | 324 ++++++++++++++++++++++++++++++++-------
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(-)
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: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Patrick Venture <venture@google.com>
2
2
3
Add support for "TX complete"/TXDC interrupt generate by real HW since
3
The reg isn't validated to be a possible register before
4
it is needed to support guests other than Linux.
4
it's dereferenced for one case. The mmio space registered
5
for the gpio device is 4KiB but there aren't that many
6
registers in the struct.
5
7
6
Based on the patch by Bill Paul as found here:
8
Cc: qemu-stable@nongnu.org
7
https://bugs.launchpad.net/qemu/+bug/1753314
9
Fixes: 526dbbe0874 ("hw/gpio: Add GPIO model for Nuvoton NPCM7xx")
8
10
Signed-off-by: Patrick Venture <venture@google.com>
9
Cc: qemu-devel@nongnu.org
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Cc: qemu-arm@nongnu.org
12
Message-id: 20250226024603.493148-1-venture@google.com
11
Cc: Bill Paul <wpaul@windriver.com>
12
Cc: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Bill Paul <wpaul@windriver.com>
14
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
15
Message-id: 20180315191141.6789-2-andrew.smirnov@gmail.com
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
14
---
19
include/hw/char/imx_serial.h | 3 +++
15
hw/gpio/npcm7xx_gpio.c | 3 +--
20
hw/char/imx_serial.c | 20 +++++++++++++++++---
16
1 file changed, 1 insertion(+), 2 deletions(-)
21
2 files changed, 20 insertions(+), 3 deletions(-)
22
17
23
diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
18
diff --git a/hw/gpio/npcm7xx_gpio.c b/hw/gpio/npcm7xx_gpio.c
24
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/char/imx_serial.h
20
--- a/hw/gpio/npcm7xx_gpio.c
26
+++ b/include/hw/char/imx_serial.h
21
+++ b/hw/gpio/npcm7xx_gpio.c
27
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gpio_regs_write(void *opaque, hwaddr addr, uint64_t v,
28
#define UCR2_RXEN (1<<1) /* Receiver enable */
23
return;
29
#define UCR2_SRST (1<<0) /* Reset complete */
24
}
30
25
31
+#define UCR4_TCEN BIT(3) /* TX complete interrupt enable */
26
- diff = s->regs[reg] ^ value;
32
+
27
-
33
#define UTS1_TXEMPTY (1<<6)
28
switch (reg) {
34
#define UTS1_RXEMPTY (1<<5)
29
case NPCM7XX_GPIO_TLOCK1:
35
#define UTS1_TXFULL (1<<4)
30
case NPCM7XX_GPIO_TLOCK2:
36
@@ -XXX,XX +XXX,XX @@ typedef struct IMXSerialState {
31
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gpio_regs_write(void *opaque, hwaddr addr, uint64_t v,
37
uint32_t ubmr;
32
case NPCM7XX_GPIO_PU:
38
uint32_t ubrc;
33
case NPCM7XX_GPIO_PD:
39
uint32_t ucr3;
34
case NPCM7XX_GPIO_IEM:
40
+ uint32_t ucr4;
35
+ diff = s->regs[reg] ^ value;
41
36
s->regs[reg] = value;
42
qemu_irq irq;
37
npcm7xx_gpio_update_pins(s, diff);
43
CharBackend chr;
44
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/char/imx_serial.c
47
+++ b/hw/char/imx_serial.c
48
@@ -XXX,XX +XXX,XX @@
49
50
static const VMStateDescription vmstate_imx_serial = {
51
.name = TYPE_IMX_SERIAL,
52
- .version_id = 1,
53
- .minimum_version_id = 1,
54
+ .version_id = 2,
55
+ .minimum_version_id = 2,
56
.fields = (VMStateField[]) {
57
VMSTATE_INT32(readbuff, IMXSerialState),
58
VMSTATE_UINT32(usr1, IMXSerialState),
59
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_serial = {
60
VMSTATE_UINT32(ubmr, IMXSerialState),
61
VMSTATE_UINT32(ubrc, IMXSerialState),
62
VMSTATE_UINT32(ucr3, IMXSerialState),
63
+ VMSTATE_UINT32(ucr4, IMXSerialState),
64
VMSTATE_END_OF_LIST()
65
},
66
};
67
@@ -XXX,XX +XXX,XX @@ static void imx_update(IMXSerialState *s)
68
* unfortunately.
69
*/
70
mask = (s->ucr1 & UCR1_TXMPTYEN) ? USR2_TXFE : 0;
71
+ /*
72
+ * TCEN and TXDC are both bit 3
73
+ */
74
+ mask |= s->ucr4 & UCR4_TCEN;
75
+
76
usr2 = s->usr2 & mask;
77
78
qemu_set_irq(s->irq, usr1 || usr2);
79
@@ -XXX,XX +XXX,XX @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
80
return s->ucr3;
81
82
case 0x23: /* UCR4 */
83
+ return s->ucr4;
84
+
85
case 0x29: /* BRM Incremental */
86
return 0x0; /* TODO */
87
88
@@ -XXX,XX +XXX,XX @@ static void imx_serial_write(void *opaque, hwaddr offset,
89
* qemu_chr_fe_write and background I/O callbacks */
90
qemu_chr_fe_write_all(&s->chr, &ch, 1);
91
s->usr1 &= ~USR1_TRDY;
92
+ s->usr2 &= ~USR2_TXDC;
93
imx_update(s);
94
s->usr1 |= USR1_TRDY;
95
+ s->usr2 |= USR2_TXDC;
96
imx_update(s);
97
}
98
break;
38
break;
99
@@ -XXX,XX +XXX,XX @@ static void imx_serial_write(void *opaque, hwaddr offset,
100
s->ucr3 = value & 0xffff;
101
break;
102
103
- case 0x2d: /* UTS1 */
104
case 0x23: /* UCR4 */
105
+ s->ucr4 = value & 0xffff;
106
+ imx_update(s);
107
+ break;
108
+
109
+ case 0x2d: /* UTS1 */
110
qemu_log_mask(LOG_UNIMP, "[%s]%s: Unimplemented reg 0x%"
111
HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset);
112
/* TODO */
113
--
39
--
114
2.16.2
40
2.43.0
115
41
116
42
diff view generated by jsdifflib
1
The BCM2837 sets the Aff1 field of the MPIDR affinity values for the
1
From: Thomas Huth <thuth@redhat.com>
2
CPUs to 0, whereas the BCM2836 uses 0xf. Set this correctly, as it
3
is required for Linux to boot.
4
2
3
The kernel that is used in the sx1 test prints the usual Linux log
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.
7
8
While we're at it, also add the test to the corresponding section
9
in the MAINTAINERS file.
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
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20180313153458.26822-8-peter.maydell@linaro.org
9
---
15
---
10
hw/arm/bcm2836.c | 11 +++++++----
16
MAINTAINERS | 1 +
11
1 file changed, 7 insertions(+), 4 deletions(-)
17
tests/functional/test_arm_sx1.py | 7 ++++---
18
2 files changed, 5 insertions(+), 3 deletions(-)
12
19
13
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
20
diff --git a/MAINTAINERS b/MAINTAINERS
14
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/bcm2836.c
22
--- a/MAINTAINERS
16
+++ b/hw/arm/bcm2836.c
23
+++ b/MAINTAINERS
17
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@ S: Maintained
18
25
F: hw/*/omap*
19
struct BCM283XInfo {
26
F: include/hw/arm/omap.h
20
const char *name;
27
F: docs/system/arm/sx1.rst
21
+ int clusterid;
28
+F: tests/functional/test_arm_sx1.py
22
};
29
23
30
IPack
24
static const BCM283XInfo bcm283x_socs[] = {
31
M: Alberto Garcia <berto@igalia.com>
25
{
32
diff --git a/tests/functional/test_arm_sx1.py b/tests/functional/test_arm_sx1.py
26
.name = TYPE_BCM2836,
33
index XXXXXXX..XXXXXXX 100755
27
+ .clusterid = 0xf,
34
--- a/tests/functional/test_arm_sx1.py
28
},
35
+++ b/tests/functional/test_arm_sx1.py
29
{
36
@@ -XXX,XX +XXX,XX @@ def test_arm_sx1_initrd(self):
30
.name = TYPE_BCM2837,
37
self.vm.add_args('-append', f'kunit.enable=0 rdinit=/sbin/init {self.CONSOLE_ARGS}')
31
+ .clusterid = 0x0,
38
self.vm.add_args('-no-reboot')
32
},
39
self.launch_kernel(zimage_path,
33
};
40
- initrd=initrd_path)
34
41
+ initrd=initrd_path,
35
@@ -XXX,XX +XXX,XX @@ static void bcm2836_init(Object *obj)
42
+ wait_for='Boot successful')
36
static void bcm2836_realize(DeviceState *dev, Error **errp)
43
self.vm.wait(timeout=120)
37
{
44
38
BCM283XState *s = BCM283X(dev);
45
def test_arm_sx1_sd(self):
39
+ BCM283XClass *bc = BCM283X_GET_CLASS(dev);
46
@@ -XXX,XX +XXX,XX @@ def test_arm_sx1_sd(self):
40
+ const BCM283XInfo *info = bc->info;
47
self.vm.add_args('-no-reboot')
41
Object *obj;
48
self.vm.add_args('-snapshot')
42
Error *err = NULL;
49
self.vm.add_args('-drive', f'format=raw,if=sd,file={sd_fs_path}')
43
int n;
50
- self.launch_kernel(zimage_path)
44
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
51
+ self.launch_kernel(zimage_path, wait_for='Boot successful')
45
qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-fiq", 0));
52
self.vm.wait(timeout=120)
46
53
47
for (n = 0; n < BCM283X_NCPUS; n++) {
54
def test_arm_sx1_flash(self):
48
- /* Mirror bcm2836, which has clusterid set to 0xf
55
@@ -XXX,XX +XXX,XX @@ def test_arm_sx1_flash(self):
49
- * TODO: this should be converted to a property of ARM_CPU
56
self.vm.add_args('-no-reboot')
50
- */
57
self.vm.add_args('-snapshot')
51
- s->cpus[n].mp_affinity = 0xF00 | n;
58
self.vm.add_args('-drive', f'format=raw,if=pflash,file={flash_path}')
52
+ /* TODO: this should be converted to a property of ARM_CPU */
59
- self.launch_kernel(zimage_path)
53
+ s->cpus[n].mp_affinity = (info->clusterid << 8) | n;
60
+ self.launch_kernel(zimage_path, wait_for='Boot successful')
54
61
self.vm.wait(timeout=120)
55
/* set periphbase/CBAR value for CPU-local registers */
62
56
object_property_set_int(OBJECT(&s->cpus[n]),
63
if __name__ == '__main__':
57
--
64
--
58
2.16.2
65
2.43.0
59
66
60
67
diff view generated by jsdifflib
1
The raspi3 has AArch64 CPUs, which means that our smpboot
1
When we are calculating timer deadlines, the correct definition of
2
code for keeping the secondary CPUs in a pen needs to have
2
whether or not to apply an offset to the physical count is described
3
a version for A64 as well as A32. Without this, the
3
in the Arm ARM DDI4087 rev L.a section D12.2.4.1. This is different
4
secondary CPUs go into an infinite loop of taking undefined
4
from when the offset should be applied for a direct read of the
5
instruction exceptions.
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: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Message-id: 20180313153458.26822-10-peter.maydell@linaro.org
18
Message-id: 20250204125009.2281315-2-peter.maydell@linaro.org
10
---
19
---
11
hw/arm/raspi.c | 41 ++++++++++++++++++++++++++++++++++++++++-
20
target/arm/helper.c | 29 +++++++++++++++++++++++++++--
12
1 file changed, 40 insertions(+), 1 deletion(-)
21
1 file changed, 27 insertions(+), 2 deletions(-)
13
22
14
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.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/arm/raspi.c
25
--- a/target/arm/helper.c
17
+++ b/hw/arm/raspi.c
26
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_phys_cnt_offset(CPUARMState *env)
19
#define BOARDSETUP_ADDR (MVBAR_ADDR + 0x20) /* board setup code */
28
return gt_phys_raw_cnt_offset(env);
20
#define FIRMWARE_ADDR_2 0x8000 /* Pi 2 loads kernel.img here by default */
21
#define FIRMWARE_ADDR_3 0x80000 /* Pi 3 loads kernel.img here by default */
22
+#define SPINTABLE_ADDR 0xd8 /* Pi 3 bootloader spintable */
23
24
/* Table of Linux board IDs for different Pi versions */
25
static const int raspi_boardid[] = {[1] = 0xc42, [2] = 0xc43, [3] = 0xc44};
26
@@ -XXX,XX +XXX,XX @@ static void write_smpboot(ARMCPU *cpu, const struct arm_boot_info *info)
27
info->smp_loader_start);
28
}
29
}
29
30
30
+static void write_smpboot64(ARMCPU *cpu, const struct arm_boot_info *info)
31
+static uint64_t gt_indirect_access_timer_offset(CPUARMState *env, int timeridx)
31
+{
32
+{
32
+ /* Unlike the AArch32 version we don't need to call the board setup hook.
33
+ /*
33
+ * The mechanism for doing the spin-table is also entirely different.
34
+ * Return the timer offset to use for indirect accesses to the timer.
34
+ * We must have four 64-bit fields at absolute addresses
35
+ * This is the Offset value as defined in D12.2.4.1 "Operation of the
35
+ * 0xd8, 0xe0, 0xe8, 0xf0 in RAM, which are the flag variables for
36
+ * CompareValue views of the timers".
36
+ * our CPUs, and which we must ensure are zero initialized before
37
+ *
37
+ * the primary CPU goes into the kernel. We put these variables inside
38
+ * The condition here is not always the same as the condition for
38
+ * a rom blob, so that the reset for ROM contents zeroes them for us.
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.
39
+ */
42
+ */
40
+ static const uint32_t smpboot[] = {
43
+ switch (timeridx) {
41
+ 0xd2801b05, /* mov x5, 0xd8 */
44
+ case GTIMER_PHYS:
42
+ 0xd53800a6, /* mrs x6, mpidr_el1 */
45
+ return gt_phys_raw_cnt_offset(env);
43
+ 0x924004c6, /* and x6, x6, #0x3 */
46
+ case GTIMER_VIRT:
44
+ 0xd503205f, /* spin: wfe */
47
+ return env->cp15.cntvoff_el2;
45
+ 0xf86678a4, /* ldr x4, [x5,x6,lsl #3] */
48
+ case GTIMER_HYP:
46
+ 0xb4ffffc4, /* cbz x4, spin */
49
+ case GTIMER_SEC:
47
+ 0xd2800000, /* mov x0, #0x0 */
50
+ case GTIMER_HYPVIRT:
48
+ 0xd2800001, /* mov x1, #0x0 */
51
+ return 0;
49
+ 0xd2800002, /* mov x2, #0x0 */
52
+ default:
50
+ 0xd2800003, /* mov x3, #0x0 */
53
+ g_assert_not_reached();
51
+ 0xd61f0080, /* br x4 */
54
+ }
52
+ };
53
+
54
+ static const uint64_t spintables[] = {
55
+ 0, 0, 0, 0
56
+ };
57
+
58
+ rom_add_blob_fixed("raspi_smpboot", smpboot, sizeof(smpboot),
59
+ info->smp_loader_start);
60
+ rom_add_blob_fixed("raspi_spintables", spintables, sizeof(spintables),
61
+ SPINTABLE_ADDR);
62
+}
55
+}
63
+
56
+
64
static void write_board_setup(ARMCPU *cpu, const struct arm_boot_info *info)
57
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
65
{
58
{
66
arm_write_secure_board_setup_dummy_smc(cpu, info, MVBAR_ADDR);
59
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
67
@@ -XXX,XX +XXX,XX @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
60
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
68
/* Pi2 and Pi3 requires SMP setup */
61
* Timer enabled: calculate and set current ISTATUS, irq, and
69
if (version >= 2) {
62
* reset timer to when ISTATUS next has to change
70
binfo.smp_loader_start = SMPBOOT_ADDR;
63
*/
71
- binfo.write_secondary_boot = write_smpboot;
64
- uint64_t offset = timeridx == GTIMER_VIRT ?
72
+ if (version == 2) {
65
- cpu->env.cp15.cntvoff_el2 : gt_phys_raw_cnt_offset(&cpu->env);
73
+ binfo.write_secondary_boot = write_smpboot;
66
+ uint64_t offset = gt_indirect_access_timer_offset(&cpu->env, timeridx);
74
+ } else {
67
uint64_t count = gt_get_countervalue(&cpu->env);
75
+ binfo.write_secondary_boot = write_smpboot64;
68
/* Note that this must be unsigned 64 bit arithmetic: */
76
+ }
69
int istatus = count - offset >= gt->cval;
77
binfo.secondary_cpu_reset_hook = reset_secondary;
78
}
79
80
--
70
--
81
2.16.2
71
2.43.0
82
72
83
73
diff view generated by jsdifflib
1
If we're directly booting a Linux kernel and the CPU supports both
1
The CNTVOFF_EL2 offset register should only be applied for accessses
2
EL3 and EL2, we start the kernel in EL2, as it expects. We must also
2
to CNTVCT_EL0 and for the EL1 virtual timer (CNTV_*). We were
3
set the SCR_EL3.HCE bit in this situation, so that the HVC
3
incorrectly applying it for the EL2 virtual timer (CNTHV_*).
4
instruction is enabled rather than UNDEFing. Otherwise at least some
5
kernels will panic when trying to initialize KVM in the guest.
6
4
5
Cc: qemu-stable@nongnu.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20180313153458.26822-4-peter.maydell@linaro.org
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Message-id: 20250204125009.2281315-3-peter.maydell@linaro.org
9
---
9
---
10
hw/arm/boot.c | 5 +++++
10
target/arm/helper.c | 2 --
11
1 file changed, 5 insertions(+)
11
1 file changed, 2 deletions(-)
12
12
13
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/boot.c
15
--- a/target/arm/helper.c
16
+++ b/hw/arm/boot.c
16
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
17
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
18
assert(!info->secure_board_setup);
18
19
}
19
switch (timeridx) {
20
20
case GTIMER_VIRT:
21
+ if (arm_feature(env, ARM_FEATURE_EL2)) {
21
- case GTIMER_HYPVIRT:
22
+ /* If we have EL2 then Linux expects the HVC insn to work */
22
offset = gt_virt_cnt_offset(env);
23
+ env->cp15.scr_el3 |= SCR_HCE;
23
break;
24
+ }
24
case GTIMER_PHYS:
25
+
25
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
26
/* Set to non-secure if not a secure boot */
26
27
if (!info->secure_boot &&
27
switch (timeridx) {
28
(cs != first_cpu || !info->secure_board_setup)) {
28
case GTIMER_VIRT:
29
- case GTIMER_HYPVIRT:
30
offset = gt_virt_cnt_offset(env);
31
break;
32
case GTIMER_PHYS:
29
--
33
--
30
2.16.2
34
2.43.0
31
35
32
36
diff view generated by jsdifflib
1
Add some assertions that if we're about to boot an AArch64 kernel,
1
When we added Secure EL2 support, we missed that this needs an update
2
the board code has not mistakenly set either secure_boot or
2
to the access code for the EL3 physical timer registers. These are
3
secure_board_setup. It doesn't make sense to set secure_boot,
3
supposed to UNDEF from Secure EL1 when Secure EL2 is enabled.
4
because all AArch64 kernels must be booted in non-secure mode.
5
4
6
It might in theory make sense to set secure_board_setup, but
5
(Note for stable backporting: for backports to branches where
7
we don't currently support that, because only the AArch32
6
CP_ACCESS_UNDEFINED is not defined, the old name to use instead
8
bootloader[] code calls this hook; bootloader_aarch64[] does not.
7
is CP_ACCESS_TRAP_UNCATEGORIZED.)
9
Since we don't have a current need for this functionality, just
10
assert that we don't try to use it. If it's needed we'll add
11
it later.
12
8
9
Cc: qemu-stable@nongnu.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
15
Message-id: 20180313153458.26822-3-peter.maydell@linaro.org
12
Message-id: 20250204125009.2281315-4-peter.maydell@linaro.org
16
---
13
---
17
hw/arm/boot.c | 7 +++++++
14
target/arm/helper.c | 3 +++
18
1 file changed, 7 insertions(+)
15
1 file changed, 3 insertions(+)
19
16
20
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
21
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/boot.c
19
--- a/target/arm/helper.c
23
+++ b/hw/arm/boot.c
20
+++ b/target/arm/helper.c
24
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
21
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
25
} else {
22
if (!arm_is_secure(env)) {
26
env->pstate = PSTATE_MODE_EL1h;
23
return CP_ACCESS_UNDEFINED;
27
}
24
}
28
+ /* AArch64 kernels never boot in secure mode */
25
+ if (arm_is_el2_enabled(env)) {
29
+ assert(!info->secure_boot);
26
+ return CP_ACCESS_UNDEFINED;
30
+ /* This hook is only supported for AArch32 currently:
27
+ }
31
+ * bootloader_aarch64[] will not call the hook, and
28
if (!(env->cp15.scr_el3 & SCR_ST)) {
32
+ * the code above has already dropped us into EL2 or EL1.
29
return CP_ACCESS_TRAP_EL3;
33
+ */
30
}
34
+ assert(!info->secure_board_setup);
35
}
36
37
/* Set to non-secure if not a secure boot */
38
--
31
--
39
2.16.2
32
2.43.0
40
33
41
34
diff view generated by jsdifflib
1
Our BCM2836 type is really a generic one that can be any of
1
Currently we handle CNTV_TVAL_EL02 by calling gt_tval_read() for the
2
the bcm283x family. Rename it accordingly. We change only
2
EL1 virt timer. This is almost correct, but the underlying
3
the names which are visible via the header file to the
3
CNTV_TVAL_EL0 register behaves slightly differently. CNTV_TVAL_EL02
4
rest of the QEMU code, leaving private function names
4
always applies the CNTVOFF_EL2 offset; CNTV_TVAL_EL0 doesn't do so if
5
in bcm2836.c as they are.
5
we're at EL2 and HCR_EL2.E2H is 1.
6
6
7
This is a preliminary to making bcm283x be an abstract
7
We were getting this wrong, because we ended up in
8
parent class to specific types for the bcm2836 and bcm2837.
8
gt_virt_cnt_offset() and did the E2H check.
9
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
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
16
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Message-id: 20250204125009.2281315-5-peter.maydell@linaro.org
13
Message-id: 20180313153458.26822-6-peter.maydell@linaro.org
14
---
18
---
15
include/hw/arm/bcm2836.h | 12 ++++++------
19
target/arm/helper.c | 36 +++++++++++++++++++++++++++---------
16
hw/arm/bcm2836.c | 17 +++++++++--------
20
1 file changed, 27 insertions(+), 9 deletions(-)
17
hw/arm/raspi.c | 16 ++++++++--------
18
3 files changed, 23 insertions(+), 22 deletions(-)
19
21
20
diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
21
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/bcm2836.h
24
--- a/target/arm/helper.c
23
+++ b/include/hw/arm/bcm2836.h
25
+++ b/target/arm/helper.c
24
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@ static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
25
#include "hw/arm/bcm2835_peripherals.h"
27
gt_recalc_timer(env_archcpu(env), timeridx);
26
#include "hw/intc/bcm2836_control.h"
28
}
27
29
28
-#define TYPE_BCM2836 "bcm2836"
30
+static uint64_t do_tval_read(CPUARMState *env, int timeridx, uint64_t offset)
29
-#define BCM2836(obj) OBJECT_CHECK(BCM2836State, (obj), TYPE_BCM2836)
31
+{
30
+#define TYPE_BCM283X "bcm283x"
32
+ return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
31
+#define BCM283X(obj) OBJECT_CHECK(BCM283XState, (obj), TYPE_BCM283X)
33
+ (gt_get_countervalue(env) - offset));
32
34
+}
33
-#define BCM2836_NCPUS 4
35
+
34
+#define BCM283X_NCPUS 4
36
static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
35
37
int timeridx)
36
-typedef struct BCM2836State {
37
+typedef struct BCM283XState {
38
/*< private >*/
39
DeviceState parent_obj;
40
/*< public >*/
41
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2836State {
42
char *cpu_type;
43
uint32_t enabled_cpus;
44
45
- ARMCPU cpus[BCM2836_NCPUS];
46
+ ARMCPU cpus[BCM283X_NCPUS];
47
BCM2836ControlState control;
48
BCM2835PeripheralState peripherals;
49
-} BCM2836State;
50
+} BCM283XState;
51
52
#endif /* BCM2836_H */
53
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/hw/arm/bcm2836.c
56
+++ b/hw/arm/bcm2836.c
57
@@ -XXX,XX +XXX,XX @@
58
59
static void bcm2836_init(Object *obj)
60
{
38
{
61
- BCM2836State *s = BCM2836(obj);
39
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
62
+ BCM283XState *s = BCM283X(obj);
40
break;
63
41
}
64
object_initialize(&s->control, sizeof(s->control), TYPE_BCM2836_CONTROL);
42
65
object_property_add_child(obj, "control", OBJECT(&s->control), NULL);
43
- return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
66
@@ -XXX,XX +XXX,XX @@ static void bcm2836_init(Object *obj)
44
- (gt_get_countervalue(env) - offset));
67
45
+ return do_tval_read(env, timeridx, offset);
68
static void bcm2836_realize(DeviceState *dev, Error **errp)
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)
69
{
74
{
70
- BCM2836State *s = BCM2836(dev);
75
- return gt_tval_read(env, ri, GTIMER_VIRT);
71
+ BCM283XState *s = BCM283X(dev);
76
+ /*
72
Object *obj;
77
+ * This is CNTV_TVAL_EL02; unlike the underlying CNTV_TVAL_EL0
73
Error *err = NULL;
78
+ * we always apply CNTVOFF_EL2. Special case that here rather
74
int n;
79
+ * than going into the generic gt_tval_read() and then having
75
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
80
+ * to re-detect that it's this register.
76
/* common peripherals from bcm2835 */
81
+ * Note that the accessfn/perms mean we know we're at EL2 or EL3 here.
77
82
+ */
78
obj = OBJECT(dev);
83
+ return do_tval_read(env, GTIMER_VIRT, env->cp15.cntvoff_el2);
79
- for (n = 0; n < BCM2836_NCPUS; n++) {
80
+ for (n = 0; n < BCM283X_NCPUS; n++) {
81
object_initialize(&s->cpus[n], sizeof(s->cpus[n]),
82
s->cpu_type);
83
object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]),
84
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
85
sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 1,
86
qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-fiq", 0));
87
88
- for (n = 0; n < BCM2836_NCPUS; n++) {
89
+ for (n = 0; n < BCM283X_NCPUS; n++) {
90
/* Mirror bcm2836, which has clusterid set to 0xf
91
* TODO: this should be converted to a property of ARM_CPU
92
*/
93
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
94
}
84
}
95
85
96
static Property bcm2836_props[] = {
86
static void gt_virt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
97
- DEFINE_PROP_STRING("cpu-type", BCM2836State, cpu_type),
87
uint64_t value)
98
- DEFINE_PROP_UINT32("enabled-cpus", BCM2836State, enabled_cpus, BCM2836_NCPUS),
88
{
99
+ DEFINE_PROP_STRING("cpu-type", BCM283XState, cpu_type),
89
- gt_tval_write(env, ri, GTIMER_VIRT, value);
100
+ DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus,
90
+ /* Similarly for writes to CNTV_TVAL_EL02 */
101
+ BCM283X_NCPUS),
91
+ do_tval_write(env, GTIMER_VIRT, value, env->cp15.cntvoff_el2);
102
DEFINE_PROP_END_OF_LIST()
103
};
104
105
@@ -XXX,XX +XXX,XX @@ static void bcm2836_class_init(ObjectClass *oc, void *data)
106
}
92
}
107
93
108
static const TypeInfo bcm2836_type_info = {
94
static void gt_virt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
109
- .name = TYPE_BCM2836,
110
+ .name = TYPE_BCM283X,
111
.parent = TYPE_DEVICE,
112
- .instance_size = sizeof(BCM2836State),
113
+ .instance_size = sizeof(BCM283XState),
114
.instance_init = bcm2836_init,
115
.class_init = bcm2836_class_init,
116
};
117
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/hw/arm/raspi.c
120
+++ b/hw/arm/raspi.c
121
@@ -XXX,XX +XXX,XX @@
122
static const int raspi_boardid[] = {[1] = 0xc42, [2] = 0xc43, [3] = 0xc44};
123
124
typedef struct RasPiState {
125
- BCM2836State soc;
126
+ BCM283XState soc;
127
MemoryRegion ram;
128
} RasPiState;
129
130
@@ -XXX,XX +XXX,XX @@ static void raspi_init(MachineState *machine, int version)
131
BusState *bus;
132
DeviceState *carddev;
133
134
- object_initialize(&s->soc, sizeof(s->soc), TYPE_BCM2836);
135
+ object_initialize(&s->soc, sizeof(s->soc), TYPE_BCM283X);
136
object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
137
&error_abort);
138
139
@@ -XXX,XX +XXX,XX @@ static void raspi2_machine_init(MachineClass *mc)
140
mc->no_floppy = 1;
141
mc->no_cdrom = 1;
142
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
143
- mc->max_cpus = BCM2836_NCPUS;
144
- mc->min_cpus = BCM2836_NCPUS;
145
- mc->default_cpus = BCM2836_NCPUS;
146
+ mc->max_cpus = BCM283X_NCPUS;
147
+ mc->min_cpus = BCM283X_NCPUS;
148
+ mc->default_cpus = BCM283X_NCPUS;
149
mc->default_ram_size = 1024 * 1024 * 1024;
150
mc->ignore_memory_transaction_failures = true;
151
};
152
@@ -XXX,XX +XXX,XX @@ static void raspi3_machine_init(MachineClass *mc)
153
mc->no_floppy = 1;
154
mc->no_cdrom = 1;
155
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a53");
156
- mc->max_cpus = BCM2836_NCPUS;
157
- mc->min_cpus = BCM2836_NCPUS;
158
- mc->default_cpus = BCM2836_NCPUS;
159
+ mc->max_cpus = BCM283X_NCPUS;
160
+ mc->min_cpus = BCM283X_NCPUS;
161
+ mc->default_cpus = BCM283X_NCPUS;
162
mc->default_ram_size = 1024 * 1024 * 1024;
163
}
164
DEFINE_MACHINE("raspi3", raspi3_machine_init)
165
--
95
--
166
2.16.2
96
2.43.0
167
97
168
98
diff view generated by jsdifflib
New patch
1
1
When reading or writing the timer registers, sometimes we need to
2
apply one of the timer offsets. Specifically, this happens for
3
direct reads of the counter registers CNTPCT_EL0 and CNTVCT_EL0 (and
4
their self-synchronized variants CNTVCTSS_EL0 and CNTPCTSS_EL0). It
5
also applies for direct reads and writes of the CNT*_TVAL_EL*
6
registers that provide the 32-bit downcounting view of each timer.
7
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
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
28
---
29
target/arm/internals.h | 5 +-
30
target/arm/helper.c | 103 +++++++++++++++++++------------------
31
target/arm/tcg/op_helper.c | 8 ++-
32
3 files changed, 62 insertions(+), 54 deletions(-)
33
34
diff --git a/target/arm/internals.h b/target/arm/internals.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/internals.h
37
+++ b/target/arm/internals.h
38
@@ -XXX,XX +XXX,XX @@ int delete_hw_watchpoint(target_ulong addr, target_ulong len, int type);
39
uint64_t gt_get_countervalue(CPUARMState *env);
40
/*
41
* Return the currently applicable offset between the system counter
42
- * and CNTVCT_EL0 (this will be either 0 or the value of CNTVOFF_EL2).
43
+ * and the counter for the specified timer, as used for direct register
44
+ * accesses.
45
*/
46
-uint64_t gt_virt_cnt_offset(CPUARMState *env);
47
+uint64_t gt_direct_access_timer_offset(CPUARMState *env, int timeridx);
48
49
/*
50
* Return mask of ARMMMUIdxBit values corresponding to an "invalidate
51
diff --git a/target/arm/helper.c b/target/arm/helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/helper.c
54
+++ b/target/arm/helper.c
55
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_phys_raw_cnt_offset(CPUARMState *env)
56
return 0;
57
}
58
59
-static uint64_t gt_phys_cnt_offset(CPUARMState *env)
60
-{
61
- if (arm_current_el(env) >= 2) {
62
- return 0;
63
- }
64
- return gt_phys_raw_cnt_offset(env);
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)
71
}
72
}
73
74
+uint64_t gt_direct_access_timer_offset(CPUARMState *env, int timeridx)
75
+{
76
+ /*
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
217
--
218
2.43.0
219
220
diff view generated by jsdifflib
1
Now we have separate types for BCM2386 and BCM2387, we might as well
1
From: Alex Bennée <alex.bennee@linaro.org>
2
just hard-code the CPU type they use rather than having it passed
2
3
through as an object property. This then lets us put the initialization
3
When FEAT_SEL2 was implemented the SEL2 timers were missed. This
4
of the CPU object in init rather than realize.
4
shows up when building the latest Hafnium with SPMC_AT_EL=2. The
5
5
actual implementation utilises the same logic as the rest of the
6
Note that this change means that it's no longer possible on
6
timers so all we need to do is:
7
the command line to use -cpu to ask for a different kind of
7
8
CPU than the SoC supports. This was never a supported thing to
8
- define the timers and their access functions
9
do anyway; we were just not sanity-checking the command line.
9
- conditionally add the correct system registers
10
10
- create a new accessfn as the rules are subtly different to the
11
This does require us to only build the bcm2837 object on
11
existing secure timer
12
TARGET_AARCH64 configs, since otherwise it won't instantiate
12
13
due to the missing cortex-a53 device and "make check" will fail.
13
Fixes: e9152ee91c (target/arm: add ARMv8.4-SEL2 system registers)
14
14
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Message-id: 20250204125009.2281315-7-peter.maydell@linaro.org
18
Message-id: 20180313153458.26822-9-peter.maydell@linaro.org
18
Cc: qemu-stable@nongnu.org
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>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
26
---
20
hw/arm/bcm2836.c | 24 +++++++++++++++---------
27
include/hw/arm/bsa.h | 2 +
21
hw/arm/raspi.c | 2 --
28
target/arm/cpu.h | 2 +
22
2 files changed, 15 insertions(+), 11 deletions(-)
29
target/arm/gtimer.h | 4 +-
23
30
target/arm/cpu.c | 4 ++
24
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
31
target/arm/helper.c | 163 +++++++++++++++++++++++++++++++++++++++++++
25
index XXXXXXX..XXXXXXX 100644
32
5 files changed, 174 insertions(+), 1 deletion(-)
26
--- a/hw/arm/bcm2836.c
33
27
+++ b/hw/arm/bcm2836.c
34
diff --git a/include/hw/arm/bsa.h b/include/hw/arm/bsa.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/arm/bsa.h
37
+++ b/include/hw/arm/bsa.h
28
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@
29
39
#define QEMU_ARM_BSA_H
30
struct BCM283XInfo {
40
31
const char *name;
41
/* These are architectural INTID values */
32
+ const char *cpu_type;
42
+#define ARCH_TIMER_S_EL2_VIRT_IRQ 19
33
int clusterid;
43
+#define ARCH_TIMER_S_EL2_IRQ 20
44
#define VIRTUAL_PMU_IRQ 23
45
#define ARCH_GIC_MAINT_IRQ 25
46
#define ARCH_TIMER_NS_EL2_IRQ 26
47
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/cpu.h
50
+++ b/target/arm/cpu.h
51
@@ -XXX,XX +XXX,XX @@ void arm_gt_vtimer_cb(void *opaque);
52
void arm_gt_htimer_cb(void *opaque);
53
void arm_gt_stimer_cb(void *opaque);
54
void arm_gt_hvtimer_cb(void *opaque);
55
+void arm_gt_sel2timer_cb(void *opaque);
56
+void arm_gt_sel2vtimer_cb(void *opaque);
57
58
unsigned int gt_cntfrq_period_ns(ARMCPU *cpu);
59
void gt_rme_post_el_change(ARMCPU *cpu, void *opaque);
60
diff --git a/target/arm/gtimer.h b/target/arm/gtimer.h
61
index XXXXXXX..XXXXXXX 100644
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
34
};
72
};
35
73
36
static const BCM283XInfo bcm283x_socs[] = {
74
#endif
37
{
75
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
38
.name = TYPE_BCM2836,
76
index XXXXXXX..XXXXXXX 100644
39
+ .cpu_type = ARM_CPU_TYPE_NAME("cortex-a15"),
77
--- a/target/arm/cpu.c
40
.clusterid = 0xf,
78
+++ b/target/arm/cpu.c
41
},
79
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
42
+#ifdef TARGET_AARCH64
80
arm_gt_stimer_cb, cpu);
43
{
81
cpu->gt_timer[GTIMER_HYPVIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
44
.name = TYPE_BCM2837,
82
arm_gt_hvtimer_cb, cpu);
45
+ .cpu_type = ARM_CPU_TYPE_NAME("cortex-a53"),
83
+ cpu->gt_timer[GTIMER_S_EL2_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
46
.clusterid = 0x0,
84
+ arm_gt_sel2timer_cb, cpu);
47
},
85
+ cpu->gt_timer[GTIMER_S_EL2_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
86
+ arm_gt_sel2vtimer_cb, cpu);
87
}
88
#endif
89
90
diff --git a/target/arm/helper.c b/target/arm/helper.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/target/arm/helper.c
93
+++ b/target/arm/helper.c
94
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
95
}
96
}
97
98
+static CPAccessResult gt_sel2timer_access(CPUARMState *env,
99
+ const ARMCPRegInfo *ri,
100
+ bool isread)
101
+{
102
+ /*
103
+ * The AArch64 register view of the secure EL2 timers are mostly
104
+ * accessible from EL3 and EL2 although can also be trapped to EL2
105
+ * from EL1 depending on nested virt config.
106
+ */
107
+ switch (arm_current_el(env)) {
108
+ case 0: /* UNDEFINED */
109
+ return CP_ACCESS_UNDEFINED;
110
+ case 1:
111
+ if (!arm_is_secure(env)) {
112
+ /* UNDEFINED */
113
+ return CP_ACCESS_UNDEFINED;
114
+ } else if (arm_hcr_el2_eff(env) & HCR_NV) {
115
+ /* Aarch64.SystemAccessTrap(EL2, 0x18) */
116
+ return CP_ACCESS_TRAP_EL2;
117
+ }
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);
160
}
161
162
+static void gt_sec_pel2_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
163
+{
164
+ gt_timer_reset(env, ri, GTIMER_S_EL2_PHYS);
165
+}
166
+
167
+static void gt_sec_pel2_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
168
+ uint64_t value)
169
+{
170
+ gt_cval_write(env, ri, GTIMER_S_EL2_PHYS, value);
171
+}
172
+
173
+static uint64_t gt_sec_pel2_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
174
+{
175
+ return gt_tval_read(env, ri, GTIMER_S_EL2_PHYS);
176
+}
177
+
178
+static void gt_sec_pel2_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
179
+ uint64_t value)
180
+{
181
+ gt_tval_write(env, ri, GTIMER_S_EL2_PHYS, value);
182
+}
183
+
184
+static void gt_sec_pel2_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
185
+ uint64_t value)
186
+{
187
+ gt_ctl_write(env, ri, GTIMER_S_EL2_PHYS, value);
188
+}
189
+
190
+static void gt_sec_vel2_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
191
+{
192
+ gt_timer_reset(env, ri, GTIMER_S_EL2_VIRT);
193
+}
194
+
195
+static void gt_sec_vel2_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
196
+ uint64_t value)
197
+{
198
+ gt_cval_write(env, ri, GTIMER_S_EL2_VIRT, value);
199
+}
200
+
201
+static uint64_t gt_sec_vel2_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
202
+{
203
+ return gt_tval_read(env, ri, GTIMER_S_EL2_VIRT);
204
+}
205
+
206
+static void gt_sec_vel2_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
207
+ uint64_t value)
208
+{
209
+ gt_tval_write(env, ri, GTIMER_S_EL2_VIRT, value);
210
+}
211
+
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
+ },
48
+#endif
295
+#endif
49
};
296
};
50
297
51
static void bcm2836_init(Object *obj)
298
static CPAccessResult nsacr_access(CPUARMState *env, const ARMCPRegInfo *ri,
52
{
53
BCM283XState *s = BCM283X(obj);
54
+ BCM283XClass *bc = BCM283X_GET_CLASS(obj);
55
+ const BCM283XInfo *info = bc->info;
56
+ int n;
57
+
58
+ for (n = 0; n < BCM283X_NCPUS; n++) {
59
+ object_initialize(&s->cpus[n], sizeof(s->cpus[n]),
60
+ info->cpu_type);
61
+ object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]),
62
+ &error_abort);
63
+ }
64
65
object_initialize(&s->control, sizeof(s->control), TYPE_BCM2836_CONTROL);
66
object_property_add_child(obj, "control", OBJECT(&s->control), NULL);
67
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
68
69
/* common peripherals from bcm2835 */
70
71
- obj = OBJECT(dev);
72
- for (n = 0; n < BCM283X_NCPUS; n++) {
73
- object_initialize(&s->cpus[n], sizeof(s->cpus[n]),
74
- s->cpu_type);
75
- object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]),
76
- &error_abort);
77
- }
78
-
79
obj = object_property_get_link(OBJECT(dev), "ram", &err);
80
if (obj == NULL) {
81
error_setg(errp, "%s: required ram link not found: %s",
82
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
83
}
84
85
static Property bcm2836_props[] = {
86
- DEFINE_PROP_STRING("cpu-type", BCM283XState, cpu_type),
87
DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus,
88
BCM283X_NCPUS),
89
DEFINE_PROP_END_OF_LIST()
90
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/hw/arm/raspi.c
93
+++ b/hw/arm/raspi.c
94
@@ -XXX,XX +XXX,XX @@ static void raspi_init(MachineState *machine, int version)
95
/* Setup the SOC */
96
object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(&s->ram),
97
&error_abort);
98
- object_property_set_str(OBJECT(&s->soc), machine->cpu_type, "cpu-type",
99
- &error_abort);
100
object_property_set_int(OBJECT(&s->soc), smp_cpus, "enabled-cpus",
101
&error_abort);
102
int board_rev = version == 3 ? 0xa02082 : 0xa21041;
103
--
299
--
104
2.16.2
300
2.43.0
105
301
106
302
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Alex Bennée <alex.bennee@linaro.org>
2
2
3
Code of imx_update() is slightly confusing since the "flags" variable
3
As we are about to add more physical and virtual timers let's make it
4
doesn't really corespond to anything in real hardware and server as a
4
clear what each timer does.
5
kitchensink accumulating events normally reported via USR1 and USR2
6
registers.
7
5
8
Change the code to explicitly evaluate state of interrupts reported
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
9
via USR1 and USR2 against corresponding masking bits and use the to
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
detemine if IRQ line should be asserted or not.
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
9
Message-id: 20250204125009.2281315-8-peter.maydell@linaro.org
12
NOTE: Check for UTS1_TXEMPTY being set has been dropped for two
10
[PMM: Add timer register name prefix to each comment]
13
reasons:
14
15
1. Emulation code implements a single character FIFO, so this flag
16
will always be set since characters are trasmitted as a part of
17
the code emulating "push" into the FIFO
18
19
2. imx_update() is really just a function doing ORing and maksing
20
of reported events, so checking for UTS1_TXEMPTY should happen,
21
if it's ever really needed should probably happen outside of
22
it.
23
24
Cc: qemu-devel@nongnu.org
25
Cc: qemu-arm@nongnu.org
26
Cc: Bill Paul <wpaul@windriver.com>
27
Cc: Peter Maydell <peter.maydell@linaro.org>
28
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
29
Message-id: 20180315191141.6789-1-andrew.smirnov@gmail.com
30
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
32
---
13
---
33
hw/char/imx_serial.c | 24 ++++++++++++++++--------
14
target/arm/gtimer.h | 10 +++++-----
34
1 file changed, 16 insertions(+), 8 deletions(-)
15
1 file changed, 5 insertions(+), 5 deletions(-)
35
16
36
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
17
diff --git a/target/arm/gtimer.h b/target/arm/gtimer.h
37
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/char/imx_serial.c
19
--- a/target/arm/gtimer.h
39
+++ b/hw/char/imx_serial.c
20
+++ b/target/arm/gtimer.h
40
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_serial = {
21
@@ -XXX,XX +XXX,XX @@
41
22
#define TARGET_ARM_GTIMER_H
42
static void imx_update(IMXSerialState *s)
23
43
{
24
enum {
44
- uint32_t flags;
25
- GTIMER_PHYS = 0,
45
+ uint32_t usr1;
26
- GTIMER_VIRT = 1,
46
+ uint32_t usr2;
27
- GTIMER_HYP = 2,
47
+ uint32_t mask;
28
- GTIMER_SEC = 3,
48
29
- GTIMER_HYPVIRT = 4,
49
- flags = (s->usr1 & s->ucr1) & (USR1_TRDY|USR1_RRDY);
30
+ GTIMER_PHYS = 0, /* CNTP_* ; EL1 physical timer */
50
- if (s->ucr1 & UCR1_TXMPTYEN) {
31
+ GTIMER_VIRT = 1, /* CNTV_* ; EL1 virtual timer */
51
- flags |= (s->uts1 & UTS1_TXEMPTY);
32
+ GTIMER_HYP = 2, /* CNTHP_* ; EL2 physical timer */
52
- } else {
33
+ GTIMER_SEC = 3, /* CNTPS_* ; EL3 physical timer */
53
- flags &= ~USR1_TRDY;
34
+ GTIMER_HYPVIRT = 4, /* CNTHV_* ; EL2 virtual timer ; only if FEAT_VHE */
54
- }
35
GTIMER_S_EL2_PHYS = 5, /* CNTHPS_* ; only if FEAT_SEL2 */
55
+ /*
36
GTIMER_S_EL2_VIRT = 6, /* CNTHVS_* ; only if FEAT_SEL2 */
56
+ * Lucky for us TRDY and RRDY has the same offset in both USR1 and
37
#define NUM_GTIMERS 7
57
+ * UCR1, so we can get away with something as simple as the
58
+ * following:
59
+ */
60
+ usr1 = s->usr1 & s->ucr1 & (USR1_TRDY | USR1_RRDY);
61
+ /*
62
+ * Bits that we want in USR2 are not as conveniently laid out,
63
+ * unfortunately.
64
+ */
65
+ mask = (s->ucr1 & UCR1_TXMPTYEN) ? USR2_TXFE : 0;
66
+ usr2 = s->usr2 & mask;
67
68
- qemu_set_irq(s->irq, !!flags);
69
+ qemu_set_irq(s->irq, usr1 || usr2);
70
}
71
72
static void imx_serial_reset(IMXSerialState *s)
73
--
38
--
74
2.16.2
39
2.43.0
75
40
76
41
diff view generated by jsdifflib
1
From: Guenter Roeck <linux@roeck-us.net>
1
From: Alex Bennée <alex.bennee@linaro.org>
2
2
3
The sabrelite machine model used by qemu-system-arm is based on the
3
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
4
Freescale/NXP i.MX6Q processor. This SoC has an on-board ethernet
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
controller which is supported in QEMU using the imx_fec.c module
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
(actually called imx.enet for this model.)
6
Message-id: 20250204125009.2281315-9-peter.maydell@linaro.org
7
7
Cc: qemu-stable@nongnu.org
8
The include/hw/arm/fsm-imx6.h file defines the interrupt vectors for the
9
imx.enet device like this:
10
11
#define FSL_IMX6_ENET_MAC_1588_IRQ 118
12
#define FSL_IMX6_ENET_MAC_IRQ 119
13
14
According to https://www.nxp.com/docs/en/reference-manual/IMX6DQRM.pdf,
15
page 225, in Table 3-1. ARM Cortex A9 domain interrupt summary,
16
interrupts are as follows.
17
18
150 ENET MAC 0 IRQ
19
151 ENET MAC 0 1588 Timer interrupt
20
21
where
22
23
150 - 32 == 118
24
151 - 32 == 119
25
26
In other words, the vector definitions in the fsl-imx6.h file are reversed.
27
28
Fixing the interrupts alone causes problems with older Linux kernels:
29
The Ethernet interface will fail to probe with Linux v4.9 and earlier.
30
Linux v4.1 and earlier will crash due to a bug in Ethernet driver probe
31
error handling. This is a Linux kernel problem, not a qemu problem:
32
the Linux kernel only worked by accident since it requested both interrupts.
33
34
For backward compatibility, generate the Ethernet interrupt on both interrupt
35
lines. This was shown to work from all Linux kernel releases starting with
36
v3.16.
37
38
Link: https://bugs.launchpad.net/qemu/+bug/1753309
39
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
40
Message-id: 1520723090-22130-1-git-send-email-linux@roeck-us.net
41
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
42
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
43
---
10
---
44
include/hw/arm/fsl-imx6.h | 4 ++--
11
hw/arm/virt.c | 2 ++
45
hw/net/imx_fec.c | 28 +++++++++++++++++++++++++++-
12
1 file changed, 2 insertions(+)
46
2 files changed, 29 insertions(+), 3 deletions(-)
47
13
48
diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h
14
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
49
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
50
--- a/include/hw/arm/fsl-imx6.h
16
--- a/hw/arm/virt.c
51
+++ b/include/hw/arm/fsl-imx6.h
17
+++ b/hw/arm/virt.c
52
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX6State {
18
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
53
#define FSL_IMX6_HDMI_MASTER_IRQ 115
19
[GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
54
#define FSL_IMX6_HDMI_CEC_IRQ 116
20
[GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
55
#define FSL_IMX6_MLB150_LOW_IRQ 117
21
[GTIMER_HYPVIRT] = ARCH_TIMER_NS_EL2_VIRT_IRQ,
56
-#define FSL_IMX6_ENET_MAC_1588_IRQ 118
22
+ [GTIMER_S_EL2_PHYS] = ARCH_TIMER_S_EL2_IRQ,
57
-#define FSL_IMX6_ENET_MAC_IRQ 119
23
+ [GTIMER_S_EL2_VIRT] = ARCH_TIMER_S_EL2_VIRT_IRQ,
58
+#define FSL_IMX6_ENET_MAC_IRQ 118
24
};
59
+#define FSL_IMX6_ENET_MAC_1588_IRQ 119
25
60
#define FSL_IMX6_PCIE1_IRQ 120
26
for (unsigned irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
61
#define FSL_IMX6_PCIE2_IRQ 121
62
#define FSL_IMX6_PCIE3_IRQ 122
63
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/net/imx_fec.c
66
+++ b/hw/net/imx_fec.c
67
@@ -XXX,XX +XXX,XX @@ static void imx_enet_write_bd(IMXENETBufDesc *bd, dma_addr_t addr)
68
69
static void imx_eth_update(IMXFECState *s)
70
{
71
- if (s->regs[ENET_EIR] & s->regs[ENET_EIMR] & ENET_INT_TS_TIMER) {
72
+ /*
73
+ * Previous versions of qemu had the ENET_INT_MAC and ENET_INT_TS_TIMER
74
+ * interrupts swapped. This worked with older versions of Linux (4.14
75
+ * and older) since Linux associated both interrupt lines with Ethernet
76
+ * MAC interrupts. Specifically,
77
+ * - Linux 4.15 and later have separate interrupt handlers for the MAC and
78
+ * timer interrupts. Those versions of Linux fail with versions of QEMU
79
+ * with swapped interrupt assignments.
80
+ * - In linux 4.14, both interrupt lines were registered with the Ethernet
81
+ * MAC interrupt handler. As a result, all versions of qemu happen to
82
+ * work, though that is accidental.
83
+ * - In Linux 4.9 and older, the timer interrupt was registered directly
84
+ * with the Ethernet MAC interrupt handler. The MAC interrupt was
85
+ * redirected to a GPIO interrupt to work around erratum ERR006687.
86
+ * This was implemented using the SOC's IOMUX block. In qemu, this GPIO
87
+ * interrupt never fired since IOMUX is currently not supported in qemu.
88
+ * Linux instead received MAC interrupts on the timer interrupt.
89
+ * As a result, qemu versions with the swapped interrupt assignment work,
90
+ * albeit accidentally, but qemu versions with the correct interrupt
91
+ * assignment fail.
92
+ *
93
+ * To ensure that all versions of Linux work, generate ENET_INT_MAC
94
+ * interrrupts on both interrupt lines. This should be changed if and when
95
+ * qemu supports IOMUX.
96
+ */
97
+ if (s->regs[ENET_EIR] & s->regs[ENET_EIMR] &
98
+ (ENET_INT_MAC | ENET_INT_TS_TIMER)) {
99
qemu_set_irq(s->irq[1], 1);
100
} else {
101
qemu_set_irq(s->irq[1], 0);
102
--
27
--
103
2.16.2
28
2.43.0
104
29
105
30
diff view generated by jsdifflib
1
From: Wei Huang <wei@redhat.com>
1
From: Alex Bennée <alex.bennee@linaro.org>
2
2
3
For guest kernel that supports KASLR, the load address can change every
3
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
4
time when guest VM runs. To find the physical base address correctly,
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
current QEMU dump searches VMCOREINFO for the string "NUMBER(phys_base)=".
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
However this string pattern is only available on x86_64. AArch64 uses a
6
Message-id: 20250204125009.2281315-10-peter.maydell@linaro.org
7
different field, called "NUMBER(PHYS_OFFSET)=". This patch makes sure
7
Cc: qemu-stable@nongnu.org
8
QEMU dump uses the correct string on AArch64.
9
10
Signed-off-by: Wei Huang <wei@redhat.com>
11
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
12
Message-id: 1520615003-20869-1-git-send-email-wei@redhat.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
9
---
15
dump.c | 14 +++++++++++---
10
hw/arm/sbsa-ref.c | 2 ++
16
1 file changed, 11 insertions(+), 3 deletions(-)
11
1 file changed, 2 insertions(+)
17
12
18
diff --git a/dump.c b/dump.c
13
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
19
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
20
--- a/dump.c
15
--- a/hw/arm/sbsa-ref.c
21
+++ b/dump.c
16
+++ b/hw/arm/sbsa-ref.c
22
@@ -XXX,XX +XXX,XX @@ static void vmcoreinfo_update_phys_base(DumpState *s)
17
@@ -XXX,XX +XXX,XX @@ static void create_gic(SBSAMachineState *sms, MemoryRegion *mem)
23
18
[GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
24
lines = g_strsplit((char *)vmci, "\n", -1);
19
[GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
25
for (i = 0; lines[i]; i++) {
20
[GTIMER_HYPVIRT] = ARCH_TIMER_NS_EL2_VIRT_IRQ,
26
- if (g_str_has_prefix(lines[i], "NUMBER(phys_base)=")) {
21
+ [GTIMER_S_EL2_PHYS] = ARCH_TIMER_S_EL2_IRQ,
27
- if (qemu_strtou64(lines[i] + 18, NULL, 16,
22
+ [GTIMER_S_EL2_VIRT] = ARCH_TIMER_S_EL2_VIRT_IRQ,
28
+ const char *prefix = NULL;
23
};
29
+
24
30
+ if (s->dump_info.d_machine == EM_X86_64) {
25
for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
31
+ prefix = "NUMBER(phys_base)=";
32
+ } else if (s->dump_info.d_machine == EM_AARCH64) {
33
+ prefix = "NUMBER(PHYS_OFFSET)=";
34
+ }
35
+
36
+ if (prefix && g_str_has_prefix(lines[i], prefix)) {
37
+ if (qemu_strtou64(lines[i] + strlen(prefix), NULL, 16,
38
&phys_base) < 0) {
39
- warn_report("Failed to read NUMBER(phys_base)=");
40
+ warn_report("Failed to read %s", prefix);
41
} else {
42
s->dump_info.phys_base = phys_base;
43
}
44
--
26
--
45
2.16.2
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 bcm2837 is pretty similar to the bcm2836, but it does have
1
All the callers of op_addr_rr_post() and op_addr_ri_post() now pass in
2
some differences. Notably, the MPIDR affinity aff1 values it
2
zero for the address_offset, so we can remove that argument.
3
sets for the CPUs are 0x0, rather than the 0xf that the bcm2836
4
uses, and if this is wrong Linux will not boot.
5
6
Rather than trying to have one device with properties that
7
configure it differently for the two cases, create two
8
separate QOM devices for the two SoCs. We use the same approach
9
as hw/arm/aspeed_soc.c and share code and have a data table
10
that might differ per-SoC. For the moment the two types don't
11
actually have different behaviour.
12
3
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20180313153458.26822-7-peter.maydell@linaro.org
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Message-id: 20250227142746.1698904-4-peter.maydell@linaro.org
16
---
8
---
17
include/hw/arm/bcm2836.h | 19 +++++++++++++++++++
9
target/arm/tcg/translate.c | 26 +++++++++++++-------------
18
hw/arm/bcm2836.c | 37 ++++++++++++++++++++++++++++++++-----
10
1 file changed, 13 insertions(+), 13 deletions(-)
19
hw/arm/raspi.c | 3 ++-
20
3 files changed, 53 insertions(+), 6 deletions(-)
21
11
22
diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
12
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
23
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/arm/bcm2836.h
14
--- a/target/arm/tcg/translate.c
25
+++ b/include/hw/arm/bcm2836.h
15
+++ b/target/arm/tcg/translate.c
26
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ static TCGv_i32 op_addr_rr_pre(DisasContext *s, arg_ldst_rr *a)
27
17
}
28
#define BCM283X_NCPUS 4
18
29
19
static void op_addr_rr_post(DisasContext *s, arg_ldst_rr *a,
30
+/* These type names are for specific SoCs; other than instantiating
20
- TCGv_i32 addr, int address_offset)
31
+ * them, code using these devices should always handle them via the
21
+ TCGv_i32 addr)
32
+ * BCM283x base class, so they have no BCM2836(obj) etc macros.
33
+ */
34
+#define TYPE_BCM2836 "bcm2836"
35
+#define TYPE_BCM2837 "bcm2837"
36
+
37
typedef struct BCM283XState {
38
/*< private >*/
39
DeviceState parent_obj;
40
@@ -XXX,XX +XXX,XX @@ typedef struct BCM283XState {
41
BCM2835PeripheralState peripherals;
42
} BCM283XState;
43
44
+typedef struct BCM283XInfo BCM283XInfo;
45
+
46
+typedef struct BCM283XClass {
47
+ DeviceClass parent_class;
48
+ const BCM283XInfo *info;
49
+} BCM283XClass;
50
+
51
+#define BCM283X_CLASS(klass) \
52
+ OBJECT_CLASS_CHECK(BCM283XClass, (klass), TYPE_BCM283X)
53
+#define BCM283X_GET_CLASS(obj) \
54
+ OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X)
55
+
56
#endif /* BCM2836_H */
57
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/hw/arm/bcm2836.c
60
+++ b/hw/arm/bcm2836.c
61
@@ -XXX,XX +XXX,XX @@
62
/* "QA7" (Pi2) interrupt controller and mailboxes etc. */
63
#define BCM2836_CONTROL_BASE 0x40000000
64
65
+struct BCM283XInfo {
66
+ const char *name;
67
+};
68
+
69
+static const BCM283XInfo bcm283x_socs[] = {
70
+ {
71
+ .name = TYPE_BCM2836,
72
+ },
73
+ {
74
+ .name = TYPE_BCM2837,
75
+ },
76
+};
77
+
78
static void bcm2836_init(Object *obj)
79
{
22
{
80
BCM283XState *s = BCM283X(obj);
23
if (!a->p) {
81
@@ -XXX,XX +XXX,XX @@ static Property bcm2836_props[] = {
24
TCGv_i32 ofs = load_reg(s, a->rm);
82
DEFINE_PROP_END_OF_LIST()
25
@@ -XXX,XX +XXX,XX @@ static void op_addr_rr_post(DisasContext *s, arg_ldst_rr *a,
83
};
26
} else if (!a->w) {
84
27
return;
85
-static void bcm2836_class_init(ObjectClass *oc, void *data)
28
}
86
+static void bcm283x_class_init(ObjectClass *oc, void *data)
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)
87
{
75
{
88
DeviceClass *dc = DEVICE_CLASS(oc);
76
+ int address_offset = 0;
89
+ BCM283XClass *bc = BCM283X_CLASS(oc);
77
if (!a->p) {
90
78
if (a->u) {
91
- dc->props = bcm2836_props;
79
- address_offset += a->imm;
92
+ bc->info = data;
80
+ address_offset = a->imm;
93
dc->realize = bcm2836_realize;
81
} else {
94
+ dc->props = bcm2836_props;
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
}
95
}
96
96
@@ -XXX,XX +XXX,XX @@ static bool op_store_ri(DisasContext *s, arg_ldst_ri *a,
97
-static const TypeInfo bcm2836_type_info = {
97
gen_aa32_st_i32(s, tmp, addr, mem_idx, mop);
98
+static const TypeInfo bcm283x_type_info = {
98
disas_set_da_iss(s, mop, issinfo);
99
.name = TYPE_BCM283X,
99
100
.parent = TYPE_DEVICE,
100
- op_addr_ri_post(s, a, addr, 0);
101
.instance_size = sizeof(BCM283XState),
101
+ op_addr_ri_post(s, a, addr);
102
.instance_init = bcm2836_init,
102
return true;
103
- .class_init = bcm2836_class_init,
104
+ .class_size = sizeof(BCM283XClass),
105
+ .abstract = true,
106
};
107
108
static void bcm2836_register_types(void)
109
{
110
- type_register_static(&bcm2836_type_info);
111
+ int i;
112
+
113
+ type_register_static(&bcm283x_type_info);
114
+ for (i = 0; i < ARRAY_SIZE(bcm283x_socs); i++) {
115
+ TypeInfo ti = {
116
+ .name = bcm283x_socs[i].name,
117
+ .parent = TYPE_BCM283X,
118
+ .class_init = bcm283x_class_init,
119
+ .class_data = (void *) &bcm283x_socs[i],
120
+ };
121
+ type_register(&ti);
122
+ }
123
}
103
}
124
104
125
type_init(bcm2836_register_types)
105
@@ -XXX,XX +XXX,XX @@ static bool op_ldrd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
126
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
106
do_ldrd_load(s, addr, a->rt, rt2);
127
index XXXXXXX..XXXXXXX 100644
107
128
--- a/hw/arm/raspi.c
108
/* LDRD w/ base writeback is undefined if the registers overlap. */
129
+++ b/hw/arm/raspi.c
109
- op_addr_ri_post(s, a, addr, 0);
130
@@ -XXX,XX +XXX,XX @@ static void raspi_init(MachineState *machine, int version)
110
+ op_addr_ri_post(s, a, addr);
131
BusState *bus;
111
return true;
132
DeviceState *carddev;
112
}
133
113
134
- object_initialize(&s->soc, sizeof(s->soc), TYPE_BCM283X);
114
@@ -XXX,XX +XXX,XX @@ static bool op_strd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
135
+ object_initialize(&s->soc, sizeof(s->soc),
115
136
+ version == 3 ? TYPE_BCM2837 : TYPE_BCM2836);
116
do_strd_store(s, addr, a->rt, rt2);
137
object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
117
138
&error_abort);
118
- op_addr_ri_post(s, a, addr, 0);
119
+ op_addr_ri_post(s, a, addr);
120
return true;
121
}
139
122
140
--
123
--
141
2.16.2
124
2.43.0
142
125
143
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 the rpi1 and 2 we want to boot the Linux kernel via some
1
Currently we call icount_start_warp_timer() from timerlist_rearm().
2
custom setup code that makes sure that the SMC instruction
2
This produces incorrect behaviour, because timerlist_rearm() is
3
acts as a no-op, because it's used for cache maintenance.
3
called, for instance, when a timer callback modifies its timer. We
4
The rpi3 boots AArch64 kernels, which don't need SMC for
4
cannot decide here to warp the timer forwards to the next timer
5
cache maintenance and always expect to be booted non-secure.
5
deadline merely because all_cpu_threads_idle() is true, because the
6
Don't fill in the aarch32-specific parts of the binfo struct.
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
10
The only valid place to choose to warp the timer forward is from the
11
main loop, when we know we have no outstanding IO or timer callbacks
12
that might be about to wake up a CPU.
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
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
42
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
43
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
44
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Message-id: 20180313153458.26822-2-peter.maydell@linaro.org
45
Tested-by: Alex Bennée <alex.bennee@linaro.org>
46
Message-id: 20250210135804.3526943-1-peter.maydell@linaro.org
12
---
47
---
13
hw/arm/raspi.c | 17 +++++++++++++----
48
util/qemu-timer.c | 4 ----
14
1 file changed, 13 insertions(+), 4 deletions(-)
49
1 file changed, 4 deletions(-)
15
50
16
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
51
diff --git a/util/qemu-timer.c b/util/qemu-timer.c
17
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/raspi.c
53
--- a/util/qemu-timer.c
19
+++ b/hw/arm/raspi.c
54
+++ b/util/qemu-timer.c
20
@@ -XXX,XX +XXX,XX @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
55
@@ -XXX,XX +XXX,XX @@ static bool timer_mod_ns_locked(QEMUTimerList *timer_list,
21
binfo.board_id = raspi_boardid[version];
56
22
binfo.ram_size = ram_size;
57
static void timerlist_rearm(QEMUTimerList *timer_list)
23
binfo.nb_cpus = smp_cpus;
58
{
24
- binfo.board_setup_addr = BOARDSETUP_ADDR;
59
- /* Interrupt execution to force deadline recalculation. */
25
- binfo.write_board_setup = write_board_setup;
60
- if (icount_enabled() && timer_list->clock->type == QEMU_CLOCK_VIRTUAL) {
26
- binfo.secure_board_setup = true;
61
- icount_start_warp_timer();
27
- binfo.secure_boot = true;
62
- }
28
+
63
timerlist_notify(timer_list);
29
+ if (version <= 2) {
64
}
30
+ /* The rpi1 and 2 require some custom setup code to run in Secure
65
31
+ * mode before booting a kernel (to set up the SMC vectors so
32
+ * that we get a no-op SMC; this is used by Linux to call the
33
+ * firmware for some cache maintenance operations.
34
+ * The rpi3 doesn't need this.
35
+ */
36
+ binfo.board_setup_addr = BOARDSETUP_ADDR;
37
+ binfo.write_board_setup = write_board_setup;
38
+ binfo.secure_board_setup = true;
39
+ binfo.secure_boot = true;
40
+ }
41
42
/* Pi2 and Pi3 requires SMP setup */
43
if (version >= 2) {
44
--
66
--
45
2.16.2
67
2.43.0
46
68
47
69
diff view generated by jsdifflib
New patch
1
Expand the example in the comment documenting MO_ATOM_SUBALIGN,
2
to be clearer about the atomicity guarantees it represents.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20250228103222.1838913-1-peter.maydell@linaro.org
7
---
8
include/exec/memop.h | 8 ++++++--
9
1 file changed, 6 insertions(+), 2 deletions(-)
10
11
diff --git a/include/exec/memop.h b/include/exec/memop.h
12
index XXXXXXX..XXXXXXX 100644
13
--- a/include/exec/memop.h
14
+++ b/include/exec/memop.h
15
@@ -XXX,XX +XXX,XX @@ typedef enum MemOp {
16
* Depending on alignment, one or both will be single-copy atomic.
17
* This is the atomicity e.g. of Arm FEAT_LSE2 LDP.
18
* MO_ATOM_SUBALIGN: the operation is single-copy atomic by parts
19
- * by the alignment. E.g. if the address is 0 mod 4, then each
20
- * 4-byte subobject is single-copy atomic.
21
+ * by the alignment. E.g. if an 8-byte value is accessed at an
22
+ * address which is 0 mod 8, then the whole 8-byte access is
23
+ * single-copy atomic; otherwise, if it is accessed at 0 mod 4
24
+ * then each 4-byte subobject is single-copy atomic; otherwise
25
+ * if it is accessed at 0 mod 2 then the four 2-byte subobjects
26
+ * are single-copy atomic.
27
* This is the atomicity e.g. of IBM Power.
28
* MO_ATOM_NONE: the operation has no atomicity requirements.
29
*
30
--
31
2.43.0
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
1
The TypeInfo and state struct for bcm2386 disagree about what the
1
From: Keith Packard <keithp@keithp.com>
2
parent class is -- the TypeInfo says it's TYPE_SYS_BUS_DEVICE,
3
but the BCM2386State struct only defines the parent_obj field
4
as DeviceState. This would have caused problems if anything
5
actually tried to treat the object as a TYPE_SYS_BUS_DEVICE.
6
Fix the TypeInfo to use TYPE_DEVICE as the parent, since we don't
7
need any of the additional functionality TYPE_SYS_BUS_DEVICE
8
provides.
9
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>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-id: 20180313153458.26822-5-peter.maydell@linaro.org
14
---
11
---
15
hw/arm/bcm2836.c | 2 +-
12
target/rx/helper.c | 2 +-
16
1 file changed, 1 insertion(+), 1 deletion(-)
13
1 file changed, 1 insertion(+), 1 deletion(-)
17
14
18
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
15
diff --git a/target/rx/helper.c b/target/rx/helper.c
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/bcm2836.c
17
--- a/target/rx/helper.c
21
+++ b/hw/arm/bcm2836.c
18
+++ b/target/rx/helper.c
22
@@ -XXX,XX +XXX,XX @@ static void bcm2836_class_init(ObjectClass *oc, void *data)
19
@@ -XXX,XX +XXX,XX @@ void rx_cpu_do_interrupt(CPUState *cs)
23
20
cpu_stl_data(env, env->isp, env->pc);
24
static const TypeInfo bcm2836_type_info = {
21
25
.name = TYPE_BCM2836,
22
if (vec < 0x100) {
26
- .parent = TYPE_SYS_BUS_DEVICE,
23
- env->pc = cpu_ldl_data(env, 0xffffffc0 + vec * 4);
27
+ .parent = TYPE_DEVICE,
24
+ env->pc = cpu_ldl_data(env, 0xffffff80 + vec * 4);
28
.instance_size = sizeof(BCM2836State),
25
} else {
29
.instance_init = bcm2836_init,
26
env->pc = cpu_ldl_data(env, env->intb + (vec & 0xff) * 4);
30
.class_init = bcm2836_class_init,
27
}
31
--
28
--
32
2.16.2
29
2.43.0
33
34
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