1
Hi; this is the latest target-arm queue. Most of the patches
1
This is a respin of my pull request from earlier this week:
2
here are RTH's FEAT_HAFDBS finally landing. I've also included
2
* versal board compile failure fixed
3
the RNG-seed randomization patches from Jason, as well as a few
3
* a few new patches:
4
more minor things. The patches include a couple of regression
4
- MAINTAINERS file fix
5
fixes:
5
- use ARRAY_SIZE macro in xilinx_zynq
6
* the resettable patch fixes a SCSI reset regression
6
- avoid an array overrun in strongarm GPIO irq handling
7
* the 'do not re-randomize on snapshot load' patches fix
7
- fix an assert running KVM on an aarch64-only host
8
record-and-replay regressions
9
8
10
thanks
9
The following changes since commit 69e2d03843412b9c076515b3aa9a71db161b6a1a:
11
-- PMM
12
10
13
The following changes since commit e750a7ace492f0b450653d4ad368a77d6f660fb8:
11
Merge remote-tracking branch 'remotes/riscv/tags/riscv-for-master-3.1-sf1' into staging (2018-11-02 13:16:13 +0000)
14
15
Merge tag 'pull-9p-20221024' of https://github.com/cschoenebeck/qemu into staging (2022-10-24 14:27:12 -0400)
16
12
17
are available in the Git repository at:
13
are available in the Git repository at:
18
14
19
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20221025
15
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20181102
20
16
21
for you to fetch changes up to e2114f701c78f76246e4b1872639dad94a6bdd21:
17
for you to fetch changes up to 6f16da53ffe4567c0353f85055df04860eb4e6fc:
22
18
23
rx: re-randomize rng-seed on reboot (2022-10-25 17:32:24 +0100)
19
hw/arm: versal: Add a virtual Xilinx Versal board (2018-11-02 14:11:31 +0000)
24
20
25
----------------------------------------------------------------
21
----------------------------------------------------------------
26
target-arm queue:
22
target-arm queue:
27
* Implement FEAT_E0PD
23
* microbit: Add the UART to our nRF51 SoC model
28
* Implement FEAT_HAFDBS
24
* Add a virtual Xilinx Versal board "xlnx-versal-virt"
29
* honor HCR_E2H and HCR_TGE in arm_excp_unmasked()
25
* hw/arm/virt: Set VIRT_COMPAT_3_0 compat
30
* hw/arm/virt: Fix devicetree warnings about the virtio-iommu node
26
* MAINTAINERS: Remove bouncing email in ARM ACPI
31
* hw/core/resettable: fix reset level counting
27
* strongarm: mask off high[31:28] bits from dir and state registers
32
* hw/hyperv/hyperv.c: Use device_cold_reset() instead of device_legacy_reset()
28
* target/arm: Conditionalize some asserts on aarch32 support
33
* imx: reload cmp timer outside of the reload ptimer transaction
29
* hw/arm/xilinx_zynq: Use the ARRAY_SIZE macro
34
* x86: do not re-randomize RNG seed on snapshot load
35
* m68k/virt: do not re-randomize RNG seed on snapshot load
36
* m68k/q800: do not re-randomize RNG seed on snapshot load
37
* arm: re-randomize rng-seed on reboot
38
* riscv: re-randomize rng-seed on reboot
39
* mips/boston: re-randomize rng-seed on reboot
40
* openrisc: re-randomize rng-seed on reboot
41
* rx: re-randomize rng-seed on reboot
42
30
43
----------------------------------------------------------------
31
----------------------------------------------------------------
44
Ake Koomsin (1):
32
Edgar E. Iglesias (2):
45
target/arm: honor HCR_E2H and HCR_TGE in arm_excp_unmasked()
33
hw/arm: versal: Add a model of Xilinx Versal SoC
34
hw/arm: versal: Add a virtual Xilinx Versal board
46
35
47
Axel Heider (1):
36
Eric Auger (1):
48
target/imx: reload cmp timer outside of the reload ptimer transaction
37
hw/arm/virt: Set VIRT_COMPAT_3_0 compat
49
38
50
Damien Hedde (1):
39
Julia Suvorova (3):
51
hw/core/resettable: fix reset level counting
40
hw/char: Implement nRF51 SoC UART
41
hw/arm/nrf51_soc: Connect UART to nRF51 SoC
42
tests/boot-serial-test: Add microbit board testcase
52
43
53
Jason A. Donenfeld (10):
44
Philippe Mathieu-Daudé (2):
54
reset: allow registering handlers that aren't called by snapshot loading
45
MAINTAINERS: Remove bouncing email in ARM ACPI
55
device-tree: add re-randomization helper function
46
hw/arm/xilinx_zynq: Use the ARRAY_SIZE macro
56
x86: do not re-randomize RNG seed on snapshot load
57
arm: re-randomize rng-seed on reboot
58
riscv: re-randomize rng-seed on reboot
59
m68k/virt: do not re-randomize RNG seed on snapshot load
60
m68k/q800: do not re-randomize RNG seed on snapshot load
61
mips/boston: re-randomize rng-seed on reboot
62
openrisc: re-randomize rng-seed on reboot
63
rx: re-randomize rng-seed on reboot
64
47
65
Jean-Philippe Brucker (1):
48
Prasad J Pandit (1):
66
hw/arm/virt: Fix devicetree warnings about the virtio-iommu node
49
strongarm: mask off high[31:28] bits from dir and state registers
67
50
68
Peter Maydell (2):
51
Richard Henderson (1):
69
target/arm: Implement FEAT_E0PD
52
target/arm: Conditionalize some asserts on aarch32 support
70
hw/hyperv/hyperv.c: Use device_cold_reset() instead of device_legacy_reset()
71
53
72
Richard Henderson (14):
54
hw/arm/Makefile.objs | 1 +
73
target/arm: Introduce regime_is_stage2
55
hw/char/Makefile.objs | 1 +
74
target/arm: Add ptw_idx to S1Translate
56
include/hw/arm/nrf51_soc.h | 3 +
75
target/arm: Add isar predicates for FEAT_HAFDBS
57
include/hw/arm/xlnx-versal.h | 122 +++++++++
76
target/arm: Extract HA and HD in aa64_va_parameters
58
include/hw/char/nrf51_uart.h | 78 ++++++
77
target/arm: Move S1_ptw_translate outside arm_ld[lq]_ptw
59
target/arm/cpu.h | 5 +
78
target/arm: Add ARMFault_UnsuppAtomicUpdate
60
hw/arm/microbit.c | 2 +
79
target/arm: Remove loop from get_phys_addr_lpae
61
hw/arm/nrf51_soc.c | 20 ++
80
target/arm: Fix fault reporting in get_phys_addr_lpae
62
hw/arm/strongarm.c | 4 +-
81
target/arm: Don't shift attrs in get_phys_addr_lpae
63
hw/arm/virt.c | 4 +
82
target/arm: Consider GP an attribute in get_phys_addr_lpae
64
hw/arm/xilinx_zynq.c | 2 +-
83
target/arm: Tidy merging of attributes from descriptor and table
65
hw/arm/xlnx-versal-virt.c | 494 ++++++++++++++++++++++++++++++++++++
84
target/arm: Implement FEAT_HAFDBS, access flag portion
66
hw/arm/xlnx-versal.c | 323 +++++++++++++++++++++++
85
target/arm: Implement FEAT_HAFDBS, dirty bit portion
67
hw/char/nrf51_uart.c | 330 ++++++++++++++++++++++++
86
target/arm: Use the max page size in a 2-stage ptw
68
target/arm/cpu.c | 15 +-
69
tests/boot-serial-test.c | 19 ++
70
MAINTAINERS | 1 -
71
default-configs/aarch64-softmmu.mak | 1 +
72
hw/char/trace-events | 4 +
73
19 files changed, 1423 insertions(+), 6 deletions(-)
74
create mode 100644 include/hw/arm/xlnx-versal.h
75
create mode 100644 include/hw/char/nrf51_uart.h
76
create mode 100644 hw/arm/xlnx-versal-virt.c
77
create mode 100644 hw/arm/xlnx-versal.c
78
create mode 100644 hw/char/nrf51_uart.c
87
79
88
docs/devel/reset.rst | 8 +-
89
docs/system/arm/emulation.rst | 2 +
90
qapi/run-state.json | 6 +-
91
include/hw/boards.h | 2 +-
92
include/sysemu/device_tree.h | 9 +
93
include/sysemu/reset.h | 5 +-
94
target/arm/cpu.h | 15 ++
95
target/arm/internals.h | 30 +++
96
hw/arm/aspeed.c | 4 +-
97
hw/arm/boot.c | 2 +
98
hw/arm/mps2-tz.c | 4 +-
99
hw/arm/virt.c | 5 +-
100
hw/core/reset.c | 17 +-
101
hw/core/resettable.c | 3 +-
102
hw/hppa/machine.c | 4 +-
103
hw/hyperv/hyperv.c | 2 +-
104
hw/i386/microvm.c | 4 +-
105
hw/i386/pc.c | 6 +-
106
hw/i386/x86.c | 2 +-
107
hw/m68k/q800.c | 33 ++-
108
hw/m68k/virt.c | 20 +-
109
hw/mips/boston.c | 3 +
110
hw/openrisc/boot.c | 3 +
111
hw/ppc/pegasos2.c | 4 +-
112
hw/ppc/pnv.c | 4 +-
113
hw/ppc/spapr.c | 4 +-
114
hw/riscv/boot.c | 3 +
115
hw/rx/rx-gdbsim.c | 3 +
116
hw/s390x/s390-virtio-ccw.c | 4 +-
117
hw/timer/imx_epit.c | 9 +-
118
migration/savevm.c | 2 +-
119
softmmu/device_tree.c | 21 ++
120
softmmu/runstate.c | 11 +-
121
target/arm/cpu.c | 24 +-
122
target/arm/cpu64.c | 2 +
123
target/arm/helper.c | 31 ++-
124
target/arm/ptw.c | 524 +++++++++++++++++++++++++++---------------
125
37 files changed, 572 insertions(+), 263 deletions(-)
diff view generated by jsdifflib
Deleted patch
1
FEAT_E0PD adds new bits E0PD0 and E0PD1 to TCR_EL1, which allow the
2
OS to forbid EL0 access to half of the address space. Since this is
3
an EL0-specific variation on the existing TCR_ELx.{EPD0,EPD1}, we can
4
implement it entirely in aa64_va_parameters().
5
1
6
This requires moving the existing regime_is_user() to internals.h
7
so that the code in helper.c can get at it.
8
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20221021160131.3531787-1-peter.maydell@linaro.org
12
---
13
docs/system/arm/emulation.rst | 1 +
14
target/arm/cpu.h | 5 +++++
15
target/arm/internals.h | 19 +++++++++++++++++++
16
target/arm/cpu64.c | 1 +
17
target/arm/helper.c | 9 +++++++++
18
target/arm/ptw.c | 19 -------------------
19
6 files changed, 35 insertions(+), 19 deletions(-)
20
21
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
22
index XXXXXXX..XXXXXXX 100644
23
--- a/docs/system/arm/emulation.rst
24
+++ b/docs/system/arm/emulation.rst
25
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
26
- FEAT_Debugv8p4 (Debug changes for v8.4)
27
- FEAT_DotProd (Advanced SIMD dot product instructions)
28
- FEAT_DoubleFault (Double Fault Extension)
29
+- FEAT_E0PD (Preventing EL0 access to halves of address maps)
30
- FEAT_ETS (Enhanced Translation Synchronization)
31
- FEAT_FCMA (Floating-point complex number instructions)
32
- FEAT_FHM (Floating-point half-precision multiplication instructions)
33
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/cpu.h
36
+++ b/target/arm/cpu.h
37
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_lva(const ARMISARegisters *id)
38
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, VARANGE) != 0;
39
}
40
41
+static inline bool isar_feature_aa64_e0pd(const ARMISARegisters *id)
42
+{
43
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, E0PD) != 0;
44
+}
45
+
46
static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id)
47
{
48
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0;
49
diff --git a/target/arm/internals.h b/target/arm/internals.h
50
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/internals.h
52
+++ b/target/arm/internals.h
53
@@ -XXX,XX +XXX,XX @@ static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
54
}
55
}
56
57
+static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
58
+{
59
+ switch (mmu_idx) {
60
+ case ARMMMUIdx_E20_0:
61
+ case ARMMMUIdx_Stage1_E0:
62
+ case ARMMMUIdx_MUser:
63
+ case ARMMMUIdx_MSUser:
64
+ case ARMMMUIdx_MUserNegPri:
65
+ case ARMMMUIdx_MSUserNegPri:
66
+ return true;
67
+ default:
68
+ return false;
69
+ case ARMMMUIdx_E10_0:
70
+ case ARMMMUIdx_E10_1:
71
+ case ARMMMUIdx_E10_1_PAN:
72
+ g_assert_not_reached();
73
+ }
74
+}
75
+
76
/* Return the SCTLR value which controls this address translation regime */
77
static inline uint64_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
78
{
79
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/target/arm/cpu64.c
82
+++ b/target/arm/cpu64.c
83
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
84
t = FIELD_DP64(t, ID_AA64MMFR2, FWB, 1); /* FEAT_S2FWB */
85
t = FIELD_DP64(t, ID_AA64MMFR2, TTL, 1); /* FEAT_TTL */
86
t = FIELD_DP64(t, ID_AA64MMFR2, BBM, 2); /* FEAT_BBM at level 2 */
87
+ t = FIELD_DP64(t, ID_AA64MMFR2, E0PD, 1); /* FEAT_E0PD */
88
cpu->isar.id_aa64mmfr2 = t;
89
90
t = cpu->isar.id_aa64zfr0;
91
diff --git a/target/arm/helper.c b/target/arm/helper.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/target/arm/helper.c
94
+++ b/target/arm/helper.c
95
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
96
ps = extract32(tcr, 16, 3);
97
ds = extract64(tcr, 32, 1);
98
} else {
99
+ bool e0pd;
100
+
101
/*
102
* Bit 55 is always between the two regions, and is canonical for
103
* determining if address tagging is enabled.
104
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
105
epd = extract32(tcr, 7, 1);
106
sh = extract32(tcr, 12, 2);
107
hpd = extract64(tcr, 41, 1);
108
+ e0pd = extract64(tcr, 55, 1);
109
} else {
110
tsz = extract32(tcr, 16, 6);
111
gran = tg1_to_gran_size(extract32(tcr, 30, 2));
112
epd = extract32(tcr, 23, 1);
113
sh = extract32(tcr, 28, 2);
114
hpd = extract64(tcr, 42, 1);
115
+ e0pd = extract64(tcr, 56, 1);
116
}
117
ps = extract64(tcr, 32, 3);
118
ds = extract64(tcr, 59, 1);
119
+
120
+ if (e0pd && cpu_isar_feature(aa64_e0pd, cpu) &&
121
+ regime_is_user(env, mmu_idx)) {
122
+ epd = true;
123
+ }
124
}
125
126
gran = sanitize_gran_size(cpu, gran, stage2);
127
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
128
index XXXXXXX..XXXXXXX 100644
129
--- a/target/arm/ptw.c
130
+++ b/target/arm/ptw.c
131
@@ -XXX,XX +XXX,XX @@ static bool regime_translation_big_endian(CPUARMState *env, ARMMMUIdx mmu_idx)
132
return (regime_sctlr(env, mmu_idx) & SCTLR_EE) != 0;
133
}
134
135
-static bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
136
-{
137
- switch (mmu_idx) {
138
- case ARMMMUIdx_E20_0:
139
- case ARMMMUIdx_Stage1_E0:
140
- case ARMMMUIdx_MUser:
141
- case ARMMMUIdx_MSUser:
142
- case ARMMMUIdx_MUserNegPri:
143
- case ARMMMUIdx_MSUserNegPri:
144
- return true;
145
- default:
146
- return false;
147
- case ARMMMUIdx_E10_0:
148
- case ARMMMUIdx_E10_1:
149
- case ARMMMUIdx_E10_1_PAN:
150
- g_assert_not_reached();
151
- }
152
-}
153
-
154
/* Return the TTBR associated with this translation regime */
155
static uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx, int ttbrn)
156
{
157
--
158
2.25.1
diff view generated by jsdifflib
1
From: Jean-Philippe Brucker <jean-philippe@linaro.org>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
The "PCI Bus Binding to: IEEE Std 1275-1994" defines the compatible
3
We are missing the VIRT_COMPAT_3_0 definition and setting.
4
string for a PCIe bus or endpoint as "pci<vendorid>,<deviceid>" or
4
Let's add them.
5
similar. Since the initial binding for PCI virtio-iommu didn't follow
6
this rule, it was modified to accept both strings and ensure backward
7
compatibility. Also, the unit-name for the node should be
8
"device,function".
9
5
10
Fix corresponding dt-validate and dtc warnings:
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
11
7
Reviewed-by: Andrew Jones <drjones@redhat.com>
12
pcie@10000000: virtio_iommu@16:compatible: ['virtio,pci-iommu'] does not contain items matching the given schema
8
Message-id: 20181024085602.16611-1-eric.auger@redhat.com
13
pcie@10000000: Unevaluated properties are not allowed (... 'virtio_iommu@16' were unexpected)
14
From schema: linux/Documentation/devicetree/bindings/pci/host-generic-pci.yaml
15
virtio_iommu@16: compatible: 'oneOf' conditional failed, one must be fixed:
16
['virtio,pci-iommu'] is too short
17
'pci1af4,1057' was expected
18
From schema: dtschema/schemas/pci/pci-bus.yaml
19
20
Warning (pci_device_reg): /pcie@10000000/virtio_iommu@16: PCI unit address format error, expected "2,0"
21
22
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
23
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
---
10
---
26
hw/arm/virt.c | 5 +++--
11
hw/arm/virt.c | 4 ++++
27
1 file changed, 3 insertions(+), 2 deletions(-)
12
1 file changed, 4 insertions(+)
28
13
29
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
14
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
30
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/virt.c
16
--- a/hw/arm/virt.c
32
+++ b/hw/arm/virt.c
17
+++ b/hw/arm/virt.c
33
@@ -XXX,XX +XXX,XX @@ static void create_smmu(const VirtMachineState *vms,
18
@@ -XXX,XX +XXX,XX @@ static void virt_machine_3_1_options(MachineClass *mc)
34
19
}
35
static void create_virtio_iommu_dt_bindings(VirtMachineState *vms)
20
DEFINE_VIRT_MACHINE_AS_LATEST(3, 1)
21
22
+#define VIRT_COMPAT_3_0 \
23
+ HW_COMPAT_3_0
24
+
25
static void virt_3_0_instance_init(Object *obj)
36
{
26
{
37
- const char compat[] = "virtio,pci-iommu";
27
virt_3_1_instance_init(obj);
38
+ const char compat[] = "virtio,pci-iommu\0pci1af4,1057";
28
@@ -XXX,XX +XXX,XX @@ static void virt_3_0_instance_init(Object *obj)
39
uint16_t bdf = vms->virtio_iommu_bdf;
29
static void virt_machine_3_0_options(MachineClass *mc)
40
MachineState *ms = MACHINE(vms);
30
{
41
char *node;
31
virt_machine_3_1_options(mc);
42
32
+ SET_MACHINE_COMPAT(mc, VIRT_COMPAT_3_0);
43
vms->iommu_phandle = qemu_fdt_alloc_phandle(ms->fdt);
33
}
44
34
DEFINE_VIRT_MACHINE(3, 0)
45
- node = g_strdup_printf("%s/virtio_iommu@%d", vms->pciehb_nodename, bdf);
35
46
+ node = g_strdup_printf("%s/virtio_iommu@%x,%x", vms->pciehb_nodename,
47
+ PCI_SLOT(bdf), PCI_FUNC(bdf));
48
qemu_fdt_add_subnode(ms->fdt, node);
49
qemu_fdt_setprop(ms->fdt, node, "compatible", compat, sizeof(compat));
50
qemu_fdt_setprop_sized_cells(ms->fdt, node, "reg",
51
--
36
--
52
2.25.1
37
2.19.1
38
39
diff view generated by jsdifflib
Deleted patch
1
From: Ake Koomsin <ake@igel.co.jp>
2
1
3
An exception targeting EL2 from lower EL is actually maskable when
4
HCR_E2H and HCR_TGE are both set. This applies to both secure and
5
non-secure Security state.
6
7
We can remove the conditions that try to suppress masking of
8
interrupts when we are Secure and the exception targets EL2 and
9
Secure EL2 is disabled. This is OK because in that situation
10
arm_phys_excp_target_el() will never return 2 as the target EL. The
11
'not if secure' check in this function was originally written before
12
arm_hcr_el2_eff(), and back then the target EL returned by
13
arm_phys_excp_target_el() could be 2 even if we were in Secure
14
EL0/EL1; but it is no longer needed.
15
16
Signed-off-by: Ake Koomsin <ake@igel.co.jp>
17
Message-id: 20221017092432.546881-1-ake@igel.co.jp
18
[PMM: Add commit message paragraph explaining why it's OK to
19
remove the checks on secure and SCR_EEL2]
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
23
target/arm/cpu.c | 24 +++++++++++++++++-------
24
1 file changed, 17 insertions(+), 7 deletions(-)
25
26
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu.c
29
+++ b/target/arm/cpu.c
30
@@ -XXX,XX +XXX,XX @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
31
if ((target_el > cur_el) && (target_el != 1)) {
32
/* Exceptions targeting a higher EL may not be maskable */
33
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
34
- /*
35
- * 64-bit masking rules are simple: exceptions to EL3
36
- * can't be masked, and exceptions to EL2 can only be
37
- * masked from Secure state. The HCR and SCR settings
38
- * don't affect the masking logic, only the interrupt routing.
39
- */
40
- if (target_el == 3 || !secure || (env->cp15.scr_el3 & SCR_EEL2)) {
41
+ switch (target_el) {
42
+ case 2:
43
+ /*
44
+ * According to ARM DDI 0487H.a, an interrupt can be masked
45
+ * when HCR_E2H and HCR_TGE are both set regardless of the
46
+ * current Security state. Note that we need to revisit this
47
+ * part again once we need to support NMI.
48
+ */
49
+ if ((hcr_el2 & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
50
+ unmasked = true;
51
+ }
52
+ break;
53
+ case 3:
54
+ /* Interrupt cannot be masked when the target EL is 3 */
55
unmasked = true;
56
+ break;
57
+ default:
58
+ g_assert_not_reached();
59
}
60
} else {
61
/*
62
--
63
2.25.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Julia Suvorova <jusual@mail.ru>
2
2
3
This fault type is to be used with FEAT_HAFDBS when
3
Not implemented: CTS/NCTS, PSEL*.
4
the guest enables hw updates, but places the tables
5
in memory where atomic updates are unsupported.
6
4
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Julia Suvorova <jusual@mail.ru>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Message-id: 20221024051851.3074715-7-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
8
---
13
target/arm/internals.h | 4 ++++
9
hw/char/Makefile.objs | 1 +
14
1 file changed, 4 insertions(+)
10
include/hw/char/nrf51_uart.h | 78 +++++++++
11
hw/char/nrf51_uart.c | 330 +++++++++++++++++++++++++++++++++++
12
hw/char/trace-events | 4 +
13
4 files changed, 413 insertions(+)
14
create mode 100644 include/hw/char/nrf51_uart.h
15
create mode 100644 hw/char/nrf51_uart.c
15
16
16
diff --git a/target/arm/internals.h b/target/arm/internals.h
17
diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/internals.h
19
--- a/hw/char/Makefile.objs
19
+++ b/target/arm/internals.h
20
+++ b/hw/char/Makefile.objs
20
@@ -XXX,XX +XXX,XX @@ typedef enum ARMFaultType {
21
@@ -XXX,XX +XXX,XX @@
21
ARMFault_AsyncExternal,
22
common-obj-$(CONFIG_IPACK) += ipoctal232.o
22
ARMFault_Debug,
23
common-obj-$(CONFIG_ESCC) += escc.o
23
ARMFault_TLBConflict,
24
+common-obj-$(CONFIG_NRF51_SOC) += nrf51_uart.o
24
+ ARMFault_UnsuppAtomicUpdate,
25
common-obj-$(CONFIG_PARALLEL) += parallel.o
25
ARMFault_Lockdown,
26
common-obj-$(CONFIG_PARALLEL) += parallel-isa.o
26
ARMFault_Exclusive,
27
common-obj-$(CONFIG_PL011) += pl011.o
27
ARMFault_ICacheMaint,
28
diff --git a/include/hw/char/nrf51_uart.h b/include/hw/char/nrf51_uart.h
28
@@ -XXX,XX +XXX,XX @@ static inline uint32_t arm_fi_to_lfsc(ARMMMUFaultInfo *fi)
29
new file mode 100644
29
case ARMFault_TLBConflict:
30
index XXXXXXX..XXXXXXX
30
fsc = 0x30;
31
--- /dev/null
31
break;
32
+++ b/include/hw/char/nrf51_uart.h
32
+ case ARMFault_UnsuppAtomicUpdate:
33
@@ -XXX,XX +XXX,XX @@
33
+ fsc = 0x31;
34
+/*
34
+ break;
35
+ * nRF51 SoC UART emulation
35
case ARMFault_Lockdown:
36
+ *
36
fsc = 0x34;
37
+ * Copyright (c) 2018 Julia Suvorova <jusual@mail.ru>
37
break;
38
+ *
39
+ * This program is free software; you can redistribute it and/or modify
40
+ * it under the terms of the GNU General Public License version 2 or
41
+ * (at your option) any later version.
42
+ */
43
+
44
+#ifndef NRF51_UART_H
45
+#define NRF51_UART_H
46
+
47
+#include "hw/sysbus.h"
48
+#include "chardev/char-fe.h"
49
+#include "hw/registerfields.h"
50
+
51
+#define UART_FIFO_LENGTH 6
52
+#define UART_BASE 0x40002000
53
+#define UART_SIZE 0x1000
54
+
55
+#define TYPE_NRF51_UART "nrf51_soc.uart"
56
+#define NRF51_UART(obj) OBJECT_CHECK(NRF51UARTState, (obj), TYPE_NRF51_UART)
57
+
58
+REG32(UART_STARTRX, 0x000)
59
+REG32(UART_STOPRX, 0x004)
60
+REG32(UART_STARTTX, 0x008)
61
+REG32(UART_STOPTX, 0x00C)
62
+REG32(UART_SUSPEND, 0x01C)
63
+
64
+REG32(UART_CTS, 0x100)
65
+REG32(UART_NCTS, 0x104)
66
+REG32(UART_RXDRDY, 0x108)
67
+REG32(UART_TXDRDY, 0x11C)
68
+REG32(UART_ERROR, 0x124)
69
+REG32(UART_RXTO, 0x144)
70
+
71
+REG32(UART_INTEN, 0x300)
72
+ FIELD(UART_INTEN, CTS, 0, 1)
73
+ FIELD(UART_INTEN, NCTS, 1, 1)
74
+ FIELD(UART_INTEN, RXDRDY, 2, 1)
75
+ FIELD(UART_INTEN, TXDRDY, 7, 1)
76
+ FIELD(UART_INTEN, ERROR, 9, 1)
77
+ FIELD(UART_INTEN, RXTO, 17, 1)
78
+REG32(UART_INTENSET, 0x304)
79
+REG32(UART_INTENCLR, 0x308)
80
+REG32(UART_ERRORSRC, 0x480)
81
+REG32(UART_ENABLE, 0x500)
82
+REG32(UART_PSELRTS, 0x508)
83
+REG32(UART_PSELTXD, 0x50C)
84
+REG32(UART_PSELCTS, 0x510)
85
+REG32(UART_PSELRXD, 0x514)
86
+REG32(UART_RXD, 0x518)
87
+REG32(UART_TXD, 0x51C)
88
+REG32(UART_BAUDRATE, 0x524)
89
+REG32(UART_CONFIG, 0x56C)
90
+
91
+typedef struct NRF51UARTState {
92
+ SysBusDevice parent_obj;
93
+
94
+ MemoryRegion iomem;
95
+ CharBackend chr;
96
+ qemu_irq irq;
97
+ guint watch_tag;
98
+
99
+ uint8_t rx_fifo[UART_FIFO_LENGTH];
100
+ unsigned int rx_fifo_pos;
101
+ unsigned int rx_fifo_len;
102
+
103
+ uint32_t reg[0x56C];
104
+
105
+ bool rx_started;
106
+ bool tx_started;
107
+ bool pending_tx_byte;
108
+ bool enabled;
109
+} NRF51UARTState;
110
+
111
+#endif
112
diff --git a/hw/char/nrf51_uart.c b/hw/char/nrf51_uart.c
113
new file mode 100644
114
index XXXXXXX..XXXXXXX
115
--- /dev/null
116
+++ b/hw/char/nrf51_uart.c
117
@@ -XXX,XX +XXX,XX @@
118
+/*
119
+ * nRF51 SoC UART emulation
120
+ *
121
+ * See nRF51 Series Reference Manual, "29 Universal Asynchronous
122
+ * Receiver/Transmitter" for hardware specifications:
123
+ * http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
124
+ *
125
+ * Copyright (c) 2018 Julia Suvorova <jusual@mail.ru>
126
+ *
127
+ * This program is free software; you can redistribute it and/or modify
128
+ * it under the terms of the GNU General Public License version 2 or
129
+ * (at your option) any later version.
130
+ */
131
+
132
+#include "qemu/osdep.h"
133
+#include "qemu/log.h"
134
+#include "hw/char/nrf51_uart.h"
135
+#include "trace.h"
136
+
137
+static void nrf51_uart_update_irq(NRF51UARTState *s)
138
+{
139
+ bool irq = false;
140
+
141
+ irq |= (s->reg[R_UART_RXDRDY] &&
142
+ (s->reg[R_UART_INTEN] & R_UART_INTEN_RXDRDY_MASK));
143
+ irq |= (s->reg[R_UART_TXDRDY] &&
144
+ (s->reg[R_UART_INTEN] & R_UART_INTEN_TXDRDY_MASK));
145
+ irq |= (s->reg[R_UART_ERROR] &&
146
+ (s->reg[R_UART_INTEN] & R_UART_INTEN_ERROR_MASK));
147
+ irq |= (s->reg[R_UART_RXTO] &&
148
+ (s->reg[R_UART_INTEN] & R_UART_INTEN_RXTO_MASK));
149
+
150
+ qemu_set_irq(s->irq, irq);
151
+}
152
+
153
+static uint64_t uart_read(void *opaque, hwaddr addr, unsigned int size)
154
+{
155
+ NRF51UARTState *s = NRF51_UART(opaque);
156
+ uint64_t r;
157
+
158
+ if (!s->enabled) {
159
+ return 0;
160
+ }
161
+
162
+ switch (addr) {
163
+ case A_UART_RXD:
164
+ r = s->rx_fifo[s->rx_fifo_pos];
165
+ if (s->rx_started && s->rx_fifo_len) {
166
+ s->rx_fifo_pos = (s->rx_fifo_pos + 1) % UART_FIFO_LENGTH;
167
+ s->rx_fifo_len--;
168
+ if (s->rx_fifo_len) {
169
+ s->reg[R_UART_RXDRDY] = 1;
170
+ nrf51_uart_update_irq(s);
171
+ }
172
+ qemu_chr_fe_accept_input(&s->chr);
173
+ }
174
+ break;
175
+ case A_UART_INTENSET:
176
+ case A_UART_INTENCLR:
177
+ case A_UART_INTEN:
178
+ r = s->reg[R_UART_INTEN];
179
+ break;
180
+ default:
181
+ r = s->reg[addr / 4];
182
+ break;
183
+ }
184
+
185
+ trace_nrf51_uart_read(addr, r, size);
186
+
187
+ return r;
188
+}
189
+
190
+static gboolean uart_transmit(GIOChannel *chan, GIOCondition cond, void *opaque)
191
+{
192
+ NRF51UARTState *s = NRF51_UART(opaque);
193
+ int r;
194
+ uint8_t c = s->reg[R_UART_TXD];
195
+
196
+ s->watch_tag = 0;
197
+
198
+ r = qemu_chr_fe_write(&s->chr, &c, 1);
199
+ if (r <= 0) {
200
+ s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
201
+ uart_transmit, s);
202
+ if (!s->watch_tag) {
203
+ /* The hardware has no transmit error reporting,
204
+ * so silently drop the byte
205
+ */
206
+ goto buffer_drained;
207
+ }
208
+ return FALSE;
209
+ }
210
+
211
+buffer_drained:
212
+ s->reg[R_UART_TXDRDY] = 1;
213
+ s->pending_tx_byte = false;
214
+ return FALSE;
215
+}
216
+
217
+static void uart_cancel_transmit(NRF51UARTState *s)
218
+{
219
+ if (s->watch_tag) {
220
+ g_source_remove(s->watch_tag);
221
+ s->watch_tag = 0;
222
+ }
223
+}
224
+
225
+static void uart_write(void *opaque, hwaddr addr,
226
+ uint64_t value, unsigned int size)
227
+{
228
+ NRF51UARTState *s = NRF51_UART(opaque);
229
+
230
+ trace_nrf51_uart_write(addr, value, size);
231
+
232
+ if (!s->enabled && (addr != A_UART_ENABLE)) {
233
+ return;
234
+ }
235
+
236
+ switch (addr) {
237
+ case A_UART_TXD:
238
+ if (!s->pending_tx_byte && s->tx_started) {
239
+ s->reg[R_UART_TXD] = value;
240
+ s->pending_tx_byte = true;
241
+ uart_transmit(NULL, G_IO_OUT, s);
242
+ }
243
+ break;
244
+ case A_UART_INTEN:
245
+ s->reg[R_UART_INTEN] = value;
246
+ break;
247
+ case A_UART_INTENSET:
248
+ s->reg[R_UART_INTEN] |= value;
249
+ break;
250
+ case A_UART_INTENCLR:
251
+ s->reg[R_UART_INTEN] &= ~value;
252
+ break;
253
+ case A_UART_TXDRDY ... A_UART_RXTO:
254
+ s->reg[addr / 4] = value;
255
+ break;
256
+ case A_UART_ERRORSRC:
257
+ s->reg[addr / 4] &= ~value;
258
+ break;
259
+ case A_UART_RXD:
260
+ break;
261
+ case A_UART_RXDRDY:
262
+ if (value == 0) {
263
+ s->reg[R_UART_RXDRDY] = 0;
264
+ }
265
+ break;
266
+ case A_UART_STARTTX:
267
+ if (value == 1) {
268
+ s->tx_started = true;
269
+ }
270
+ break;
271
+ case A_UART_STARTRX:
272
+ if (value == 1) {
273
+ s->rx_started = true;
274
+ }
275
+ break;
276
+ case A_UART_ENABLE:
277
+ if (value) {
278
+ if (value == 4) {
279
+ s->enabled = true;
280
+ }
281
+ break;
282
+ }
283
+ s->enabled = false;
284
+ value = 1;
285
+ /* fall through */
286
+ case A_UART_SUSPEND:
287
+ case A_UART_STOPTX:
288
+ if (value == 1) {
289
+ s->tx_started = false;
290
+ }
291
+ /* fall through */
292
+ case A_UART_STOPRX:
293
+ if (addr != A_UART_STOPTX && value == 1) {
294
+ s->rx_started = false;
295
+ s->reg[R_UART_RXTO] = 1;
296
+ }
297
+ break;
298
+ default:
299
+ s->reg[addr / 4] = value;
300
+ break;
301
+ }
302
+ nrf51_uart_update_irq(s);
303
+}
304
+
305
+static const MemoryRegionOps uart_ops = {
306
+ .read = uart_read,
307
+ .write = uart_write,
308
+ .endianness = DEVICE_LITTLE_ENDIAN,
309
+};
310
+
311
+static void nrf51_uart_reset(DeviceState *dev)
312
+{
313
+ NRF51UARTState *s = NRF51_UART(dev);
314
+
315
+ s->pending_tx_byte = 0;
316
+
317
+ uart_cancel_transmit(s);
318
+
319
+ memset(s->reg, 0, sizeof(s->reg));
320
+
321
+ s->reg[R_UART_PSELRTS] = 0xFFFFFFFF;
322
+ s->reg[R_UART_PSELTXD] = 0xFFFFFFFF;
323
+ s->reg[R_UART_PSELCTS] = 0xFFFFFFFF;
324
+ s->reg[R_UART_PSELRXD] = 0xFFFFFFFF;
325
+ s->reg[R_UART_BAUDRATE] = 0x4000000;
326
+
327
+ s->rx_fifo_len = 0;
328
+ s->rx_fifo_pos = 0;
329
+ s->rx_started = false;
330
+ s->tx_started = false;
331
+ s->enabled = false;
332
+}
333
+
334
+static void uart_receive(void *opaque, const uint8_t *buf, int size)
335
+{
336
+
337
+ NRF51UARTState *s = NRF51_UART(opaque);
338
+ int i;
339
+
340
+ if (size == 0 || s->rx_fifo_len >= UART_FIFO_LENGTH) {
341
+ return;
342
+ }
343
+
344
+ for (i = 0; i < size; i++) {
345
+ uint32_t pos = (s->rx_fifo_pos + s->rx_fifo_len) % UART_FIFO_LENGTH;
346
+ s->rx_fifo[pos] = buf[i];
347
+ s->rx_fifo_len++;
348
+ }
349
+
350
+ s->reg[R_UART_RXDRDY] = 1;
351
+ nrf51_uart_update_irq(s);
352
+}
353
+
354
+static int uart_can_receive(void *opaque)
355
+{
356
+ NRF51UARTState *s = NRF51_UART(opaque);
357
+
358
+ return s->rx_started ? (UART_FIFO_LENGTH - s->rx_fifo_len) : 0;
359
+}
360
+
361
+static void uart_event(void *opaque, int event)
362
+{
363
+ NRF51UARTState *s = NRF51_UART(opaque);
364
+
365
+ if (event == CHR_EVENT_BREAK) {
366
+ s->reg[R_UART_ERRORSRC] |= 3;
367
+ s->reg[R_UART_ERROR] = 1;
368
+ nrf51_uart_update_irq(s);
369
+ }
370
+}
371
+
372
+static void nrf51_uart_realize(DeviceState *dev, Error **errp)
373
+{
374
+ NRF51UARTState *s = NRF51_UART(dev);
375
+
376
+ qemu_chr_fe_set_handlers(&s->chr, uart_can_receive, uart_receive,
377
+ uart_event, NULL, s, NULL, true);
378
+}
379
+
380
+static void nrf51_uart_init(Object *obj)
381
+{
382
+ NRF51UARTState *s = NRF51_UART(obj);
383
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
384
+
385
+ memory_region_init_io(&s->iomem, obj, &uart_ops, s,
386
+ "nrf51_soc.uart", UART_SIZE);
387
+ sysbus_init_mmio(sbd, &s->iomem);
388
+ sysbus_init_irq(sbd, &s->irq);
389
+}
390
+
391
+static int nrf51_uart_post_load(void *opaque, int version_id)
392
+{
393
+ NRF51UARTState *s = NRF51_UART(opaque);
394
+
395
+ if (s->pending_tx_byte) {
396
+ s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
397
+ uart_transmit, s);
398
+ }
399
+
400
+ return 0;
401
+}
402
+
403
+static const VMStateDescription nrf51_uart_vmstate = {
404
+ .name = "nrf51_soc.uart",
405
+ .post_load = nrf51_uart_post_load,
406
+ .fields = (VMStateField[]) {
407
+ VMSTATE_UINT32_ARRAY(reg, NRF51UARTState, 0x56C),
408
+ VMSTATE_UINT8_ARRAY(rx_fifo, NRF51UARTState, UART_FIFO_LENGTH),
409
+ VMSTATE_UINT32(rx_fifo_pos, NRF51UARTState),
410
+ VMSTATE_UINT32(rx_fifo_len, NRF51UARTState),
411
+ VMSTATE_BOOL(rx_started, NRF51UARTState),
412
+ VMSTATE_BOOL(tx_started, NRF51UARTState),
413
+ VMSTATE_BOOL(pending_tx_byte, NRF51UARTState),
414
+ VMSTATE_BOOL(enabled, NRF51UARTState),
415
+ VMSTATE_END_OF_LIST()
416
+ }
417
+};
418
+
419
+static Property nrf51_uart_properties[] = {
420
+ DEFINE_PROP_CHR("chardev", NRF51UARTState, chr),
421
+ DEFINE_PROP_END_OF_LIST(),
422
+};
423
+
424
+static void nrf51_uart_class_init(ObjectClass *klass, void *data)
425
+{
426
+ DeviceClass *dc = DEVICE_CLASS(klass);
427
+
428
+ dc->reset = nrf51_uart_reset;
429
+ dc->realize = nrf51_uart_realize;
430
+ dc->props = nrf51_uart_properties;
431
+ dc->vmsd = &nrf51_uart_vmstate;
432
+}
433
+
434
+static const TypeInfo nrf51_uart_info = {
435
+ .name = TYPE_NRF51_UART,
436
+ .parent = TYPE_SYS_BUS_DEVICE,
437
+ .instance_size = sizeof(NRF51UARTState),
438
+ .instance_init = nrf51_uart_init,
439
+ .class_init = nrf51_uart_class_init
440
+};
441
+
442
+static void nrf51_uart_register_types(void)
443
+{
444
+ type_register_static(&nrf51_uart_info);
445
+}
446
+
447
+type_init(nrf51_uart_register_types)
448
diff --git a/hw/char/trace-events b/hw/char/trace-events
449
index XXXXXXX..XXXXXXX 100644
450
--- a/hw/char/trace-events
451
+++ b/hw/char/trace-events
452
@@ -XXX,XX +XXX,XX @@ cmsdk_apb_uart_receive(uint8_t c) "CMSDK APB UART: got character 0x%x from backe
453
cmsdk_apb_uart_tx_pending(void) "CMSDK APB UART: character send to backend pending"
454
cmsdk_apb_uart_tx(uint8_t c) "CMSDK APB UART: character 0x%x sent to backend"
455
cmsdk_apb_uart_set_params(int speed) "CMSDK APB UART: params set to %d 8N1"
456
+
457
+# hw/char/nrf51_uart.c
458
+nrf51_uart_read(uint64_t addr, uint64_t r, unsigned int size) "addr 0x%" PRIx64 " value 0x%" PRIx64 " size %u"
459
+nrf51_uart_write(uint64_t addr, uint64_t value, unsigned int size) "addr 0x%" PRIx64 " value 0x%" PRIx64 " size %u"
38
--
460
--
39
2.25.1
461
2.19.1
40
462
41
463
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Julia Suvorova <jusual@mail.ru>
2
2
3
Reduce the amount of typing required for this check.
3
Wire up nRF51 UART in the corresponding SoC.
4
4
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Julia Suvorova <jusual@mail.ru>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 20221024051851.3074715-2-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
target/arm/internals.h | 5 +++++
11
include/hw/arm/nrf51_soc.h | 3 +++
12
target/arm/helper.c | 14 +++++---------
12
hw/arm/microbit.c | 2 ++
13
target/arm/ptw.c | 14 ++++++--------
13
hw/arm/nrf51_soc.c | 20 ++++++++++++++++++++
14
3 files changed, 16 insertions(+), 17 deletions(-)
14
3 files changed, 25 insertions(+)
15
15
16
diff --git a/target/arm/internals.h b/target/arm/internals.h
16
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/internals.h
18
--- a/include/hw/arm/nrf51_soc.h
19
+++ b/target/arm/internals.h
19
+++ b/include/hw/arm/nrf51_soc.h
20
@@ -XXX,XX +XXX,XX @@ static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx)
20
@@ -XXX,XX +XXX,XX @@
21
22
#include "hw/sysbus.h"
23
#include "hw/arm/armv7m.h"
24
+#include "hw/char/nrf51_uart.h"
25
26
#define TYPE_NRF51_SOC "nrf51-soc"
27
#define NRF51_SOC(obj) \
28
@@ -XXX,XX +XXX,XX @@ typedef struct NRF51State {
29
/*< public >*/
30
ARMv7MState cpu;
31
32
+ NRF51UARTState uart;
33
+
34
MemoryRegion iomem;
35
MemoryRegion sram;
36
MemoryRegion flash;
37
diff --git a/hw/arm/microbit.c b/hw/arm/microbit.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/arm/microbit.c
40
+++ b/hw/arm/microbit.c
41
@@ -XXX,XX +XXX,XX @@
42
#include "qapi/error.h"
43
#include "hw/boards.h"
44
#include "hw/arm/arm.h"
45
+#include "sysemu/sysemu.h"
46
#include "exec/address-spaces.h"
47
48
#include "hw/arm/nrf51_soc.h"
49
@@ -XXX,XX +XXX,XX @@ static void microbit_init(MachineState *machine)
50
51
sysbus_init_child_obj(OBJECT(machine), "nrf51", soc, sizeof(s->nrf51),
52
TYPE_NRF51_SOC);
53
+ qdev_prop_set_chr(DEVICE(&s->nrf51), "serial0", serial_hd(0));
54
object_property_set_link(soc, OBJECT(system_memory), "memory",
55
&error_fatal);
56
object_property_set_bool(soc, true, "realized", &error_fatal);
57
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/hw/arm/nrf51_soc.c
60
+++ b/hw/arm/nrf51_soc.c
61
@@ -XXX,XX +XXX,XX @@
62
#define NRF51822_FLASH_SIZE (256 * 1024)
63
#define NRF51822_SRAM_SIZE (16 * 1024)
64
65
+#define BASE_TO_IRQ(base) ((base >> 12) & 0x1F)
66
+
67
static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
68
{
69
NRF51State *s = NRF51_SOC(dev_soc);
70
+ MemoryRegion *mr;
71
Error *err = NULL;
72
73
if (!s->board_memory) {
74
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
21
}
75
}
76
memory_region_add_subregion(&s->container, SRAM_BASE, &s->sram);
77
78
+ /* UART */
79
+ object_property_set_bool(OBJECT(&s->uart), true, "realized", &err);
80
+ if (err) {
81
+ error_propagate(errp, err);
82
+ return;
83
+ }
84
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart), 0);
85
+ memory_region_add_subregion_overlap(&s->container, UART_BASE, mr, 0);
86
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart), 0,
87
+ qdev_get_gpio_in(DEVICE(&s->cpu),
88
+ BASE_TO_IRQ(UART_BASE)));
89
+
90
create_unimplemented_device("nrf51_soc.io", IOMEM_BASE, IOMEM_SIZE);
91
create_unimplemented_device("nrf51_soc.ficr", FICR_BASE, FICR_SIZE);
92
create_unimplemented_device("nrf51_soc.private",
93
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_init(Object *obj)
94
qdev_prop_set_string(DEVICE(&s->cpu), "cpu-type",
95
ARM_CPU_TYPE_NAME("cortex-m0"));
96
qdev_prop_set_uint32(DEVICE(&s->cpu), "num-irq", 32);
97
+
98
+ sysbus_init_child_obj(obj, "uart", &s->uart, sizeof(s->uart),
99
+ TYPE_NRF51_UART);
100
+ object_property_add_alias(obj, "serial0", OBJECT(&s->uart), "chardev",
101
+ &error_abort);
22
}
102
}
23
103
24
+static inline bool regime_is_stage2(ARMMMUIdx mmu_idx)
104
static Property nrf51_soc_properties[] = {
25
+{
26
+ return mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S;
27
+}
28
+
29
/* Return the exception level which controls this address translation regime */
30
static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
31
{
32
diff --git a/target/arm/helper.c b/target/arm/helper.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/helper.c
35
+++ b/target/arm/helper.c
36
@@ -XXX,XX +XXX,XX @@ int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx)
37
{
38
if (regime_has_2_ranges(mmu_idx)) {
39
return extract64(tcr, 37, 2);
40
- } else if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) {
41
+ } else if (regime_is_stage2(mmu_idx)) {
42
return 0; /* VTCR_EL2 */
43
} else {
44
/* Replicate the single TBI bit so we always have 2 bits. */
45
@@ -XXX,XX +XXX,XX @@ int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mmu_idx)
46
{
47
if (regime_has_2_ranges(mmu_idx)) {
48
return extract64(tcr, 51, 2);
49
- } else if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) {
50
+ } else if (regime_is_stage2(mmu_idx)) {
51
return 0; /* VTCR_EL2 */
52
} else {
53
/* Replicate the single TBID bit so we always have 2 bits. */
54
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
55
int select, tsz, tbi, max_tsz, min_tsz, ps, sh;
56
ARMGranuleSize gran;
57
ARMCPU *cpu = env_archcpu(env);
58
- bool stage2 = mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S;
59
+ bool stage2 = regime_is_stage2(mmu_idx);
60
61
if (!regime_has_2_ranges(mmu_idx)) {
62
select = 0;
63
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
64
}
65
ds = false;
66
} else if (ds) {
67
- switch (mmu_idx) {
68
- case ARMMMUIdx_Stage2:
69
- case ARMMMUIdx_Stage2_S:
70
+ if (regime_is_stage2(mmu_idx)) {
71
if (gran == Gran16K) {
72
ds = cpu_isar_feature(aa64_tgran16_2_lpa2, cpu);
73
} else {
74
ds = cpu_isar_feature(aa64_tgran4_2_lpa2, cpu);
75
}
76
- break;
77
- default:
78
+ } else {
79
if (gran == Gran16K) {
80
ds = cpu_isar_feature(aa64_tgran16_lpa2, cpu);
81
} else {
82
ds = cpu_isar_feature(aa64_tgran4_lpa2, cpu);
83
}
84
- break;
85
}
86
if (ds) {
87
min_tsz = 12;
88
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/target/arm/ptw.c
91
+++ b/target/arm/ptw.c
92
@@ -XXX,XX +XXX,XX @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
93
bool have_wxn;
94
int wxn = 0;
95
96
- assert(mmu_idx != ARMMMUIdx_Stage2);
97
- assert(mmu_idx != ARMMMUIdx_Stage2_S);
98
+ assert(!regime_is_stage2(mmu_idx));
99
100
user_rw = simple_ap_to_rw_prot_is_user(ap, true);
101
if (is_user) {
102
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
103
goto do_fault;
104
}
105
106
- if (mmu_idx != ARMMMUIdx_Stage2 && mmu_idx != ARMMMUIdx_Stage2_S) {
107
+ if (!regime_is_stage2(mmu_idx)) {
108
/*
109
* The starting level depends on the virtual address size (which can
110
* be up to 48 bits) and the translation granule size. It indicates
111
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
112
attrs = extract64(descriptor, 2, 10)
113
| (extract64(descriptor, 52, 12) << 10);
114
115
- if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) {
116
+ if (regime_is_stage2(mmu_idx)) {
117
/* Stage 2 table descriptors do not include any attribute fields */
118
break;
119
}
120
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
121
122
ap = extract32(attrs, 4, 2);
123
124
- if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) {
125
+ if (regime_is_stage2(mmu_idx)) {
126
ns = mmu_idx == ARMMMUIdx_Stage2;
127
xn = extract32(attrs, 11, 2);
128
result->f.prot = get_S2prot(env, ap, xn, s1_is_el0);
129
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
130
result->f.guarded = guarded;
131
}
132
133
- if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) {
134
+ if (regime_is_stage2(mmu_idx)) {
135
result->cacheattrs.is_s2_format = true;
136
result->cacheattrs.attrs = extract32(attrs, 0, 4);
137
} else {
138
@@ -XXX,XX +XXX,XX @@ do_fault:
139
fi->type = fault_type;
140
fi->level = level;
141
/* Tag the error as S2 for failed S1 PTW at S2 or ordinary S2. */
142
- fi->stage2 = fi->s1ptw || (mmu_idx == ARMMMUIdx_Stage2 ||
143
- mmu_idx == ARMMMUIdx_Stage2_S);
144
+ fi->stage2 = fi->s1ptw || regime_is_stage2(mmu_idx);
145
fi->s1ns = mmu_idx == ARMMMUIdx_Stage2;
146
return true;
147
}
148
--
105
--
149
2.25.1
106
2.19.1
150
107
151
108
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Julia Suvorova <jusual@mail.ru>
2
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
New mini-kernel test for nRF51 SoC UART.
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Julia Suvorova <jusual@mail.ru>
6
Message-id: 20221024051851.3074715-5-richard.henderson@linaro.org
6
Acked-by: Thomas Huth <thuth@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
---
9
target/arm/internals.h | 2 ++
10
tests/boot-serial-test.c | 19 +++++++++++++++++++
10
target/arm/helper.c | 8 +++++++-
11
1 file changed, 19 insertions(+)
11
2 files changed, 9 insertions(+), 1 deletion(-)
12
12
13
diff --git a/target/arm/internals.h b/target/arm/internals.h
13
diff --git a/tests/boot-serial-test.c b/tests/boot-serial-test.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/internals.h
15
--- a/tests/boot-serial-test.c
16
+++ b/target/arm/internals.h
16
+++ b/tests/boot-serial-test.c
17
@@ -XXX,XX +XXX,XX @@ typedef struct ARMVAParameters {
17
@@ -XXX,XX +XXX,XX @@ static const uint8_t kernel_aarch64[] = {
18
bool hpd : 1;
18
0xfd, 0xff, 0xff, 0x17, /* b -12 (loop) */
19
bool tsz_oob : 1; /* tsz has been clamped to legal range */
19
};
20
bool ds : 1;
20
21
+ bool ha : 1;
21
+static const uint8_t kernel_nrf51[] = {
22
+ bool hd : 1;
22
+ 0x00, 0x00, 0x00, 0x00, /* Stack top address */
23
ARMGranuleSize gran : 2;
23
+ 0x09, 0x00, 0x00, 0x00, /* Reset handler address */
24
} ARMVAParameters;
24
+ 0x04, 0x4a, /* ldr r2, [pc, #16] Get ENABLE */
25
25
+ 0x04, 0x21, /* movs r1, #4 */
26
diff --git a/target/arm/helper.c b/target/arm/helper.c
26
+ 0x11, 0x60, /* str r1, [r2] */
27
index XXXXXXX..XXXXXXX 100644
27
+ 0x04, 0x4a, /* ldr r2, [pc, #16] Get STARTTX */
28
--- a/target/arm/helper.c
28
+ 0x01, 0x21, /* movs r1, #1 */
29
+++ b/target/arm/helper.c
29
+ 0x11, 0x60, /* str r1, [r2] */
30
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
30
+ 0x03, 0x4a, /* ldr r2, [pc, #12] Get TXD */
31
ARMMMUIdx mmu_idx, bool data)
31
+ 0x54, 0x21, /* movs r1, 'T' */
32
{
32
+ 0x11, 0x60, /* str r1, [r2] */
33
uint64_t tcr = regime_tcr(env, mmu_idx);
33
+ 0xfe, 0xe7, /* b . */
34
- bool epd, hpd, tsz_oob, ds;
34
+ 0x00, 0x25, 0x00, 0x40, /* 0x40002500 = UART ENABLE */
35
+ bool epd, hpd, tsz_oob, ds, ha, hd;
35
+ 0x08, 0x20, 0x00, 0x40, /* 0x40002008 = UART STARTTX */
36
int select, tsz, tbi, max_tsz, min_tsz, ps, sh;
36
+ 0x1c, 0x25, 0x00, 0x40 /* 0x4000251c = UART TXD */
37
ARMGranuleSize gran;
37
+};
38
ARMCPU *cpu = env_archcpu(env);
38
+
39
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
39
typedef struct testdef {
40
epd = false;
40
const char *arch; /* Target architecture */
41
sh = extract32(tcr, 12, 2);
41
const char *machine; /* Name of the machine */
42
ps = extract32(tcr, 16, 3);
42
@@ -XXX,XX +XXX,XX @@ static testdef_t tests[] = {
43
+ ha = extract32(tcr, 21, 1) && cpu_isar_feature(aa64_hafs, cpu);
43
{ "hppa", "hppa", "", "SeaBIOS wants SYSTEM HALT" },
44
+ hd = extract32(tcr, 22, 1) && cpu_isar_feature(aa64_hdbs, cpu);
44
{ "aarch64", "virt", "-cpu cortex-a57", "TT", sizeof(kernel_aarch64),
45
ds = extract64(tcr, 32, 1);
45
kernel_aarch64 },
46
} else {
46
+ { "arm", "microbit", "", "T", sizeof(kernel_nrf51), kernel_nrf51 },
47
bool e0pd;
47
48
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
48
{ NULL }
49
e0pd = extract64(tcr, 56, 1);
49
};
50
}
51
ps = extract64(tcr, 32, 3);
52
+ ha = extract64(tcr, 39, 1) && cpu_isar_feature(aa64_hafs, cpu);
53
+ hd = extract64(tcr, 40, 1) && cpu_isar_feature(aa64_hdbs, cpu);
54
ds = extract64(tcr, 59, 1);
55
56
if (e0pd && cpu_isar_feature(aa64_e0pd, cpu) &&
57
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
58
.hpd = hpd,
59
.tsz_oob = tsz_oob,
60
.ds = ds,
61
+ .ha = ha,
62
+ .hd = ha && hd,
63
.gran = gran,
64
};
65
}
66
--
50
--
67
2.25.1
51
2.19.1
68
52
69
53
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
The code for handling the reset level count in the Resettable code
3
Shannon Zhao's email at Huawei is bouncing: remove it.
4
has two issues:
5
4
6
The reset count is only decremented for the 1->0 case. This means
5
X-Failed-Recipients: zhaoshenglong@huawei.com
7
that if there's ever a nested reset that takes the count to 2 then it
6
** Address not found **
8
will never again be decremented. Eventually the count will exceed
7
Your message wasn't delivered to zhaoshenglong@huawei.com because the address couldn't be found, or is unable to receive mail.
9
the '50' limit in resettable_phase_enter() and QEMU will trip over
10
the assertion failure. The repro case in issue 1266 is an example of
11
this that happens now the SCSI subsystem uses three-phase reset.
12
8
13
Secondly, the count is decremented only after the exit phase handler
9
Note that the section still contains his personal email (see e59f13d76bb).
14
is called. Moving the reset count decrement from "just after" to
15
"just before" calling the exit phase handler allows
16
resettable_is_in_reset() to return false during the handler
17
execution.
18
10
19
This simplifies reset handling in resettable devices. Typically, a
11
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
20
function that updates the device state will just need to read the
12
Acked-by: Shannon Zhao <shannon.zhaosl@gmail.com>
21
current reset state and not anymore treat the "in a reset-exit
13
Message-id: 20181029195931.8747-1-philmd@redhat.com
22
transition" as a special case.
23
24
Note that the semantics change to the *_is_in_reset() functions
25
will have no effect on the current codebase, because only two
26
devices (hw/char/cadence_uart.c and hw/misc/zynq_sclr.c) currently
27
call those functions, and in neither case do they do it from the
28
device's exit phase methed.
29
30
Fixes: 4a5fc890 ("scsi: Use device_cold_reset() and bus_cold_reset()")
31
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1266
32
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
33
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
34
Reported-by: Michael Peter <michael.peter@hensoldt-cyber.com>
35
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
36
Message-id: 20221020142749.3357951-1-peter.maydell@linaro.org
37
Buglink: https://bugs.launchpad.net/qemu/+bug/1905297
38
Reported-by: Michael Peter <michael.peter@hensoldt-cyber.com>
39
[PMM: adjust the docs paragraph changed to get the name of the
40
'enter' phase right and to clarify exactly when the count is
41
adjusted; rewrite the commit message]
42
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
43
---
15
---
44
docs/devel/reset.rst | 8 +++++---
16
MAINTAINERS | 1 -
45
hw/core/resettable.c | 3 +--
17
1 file changed, 1 deletion(-)
46
2 files changed, 6 insertions(+), 5 deletions(-)
47
18
48
diff --git a/docs/devel/reset.rst b/docs/devel/reset.rst
19
diff --git a/MAINTAINERS b/MAINTAINERS
49
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
50
--- a/docs/devel/reset.rst
21
--- a/MAINTAINERS
51
+++ b/docs/devel/reset.rst
22
+++ b/MAINTAINERS
52
@@ -XXX,XX +XXX,XX @@ Polling the reset state
23
@@ -XXX,XX +XXX,XX @@ F: hw/*/xlnx*.c
53
Resettable interface provides the ``resettable_is_in_reset()`` function.
24
F: include/hw/*/xlnx*.h
54
This function returns true if the object parameter is currently under reset.
25
55
26
ARM ACPI Subsystem
56
-An object is under reset from the beginning of the *init* phase to the end of
27
-M: Shannon Zhao <zhaoshenglong@huawei.com>
57
-the *exit* phase. During all three phases, the function will return that the
28
M: Shannon Zhao <shannon.zhaosl@gmail.com>
58
-object is in reset.
29
L: qemu-arm@nongnu.org
59
+An object is under reset from the beginning of the *enter* phase (before
30
S: Maintained
60
+either its children or its own enter method is called) to the *exit*
61
+phase. During *enter* and *hold* phase only, the function will return that the
62
+object is in reset. The state is changed after the *exit* is propagated to
63
+its children and just before calling the object's own *exit* method.
64
65
This function may be used if the object behavior has to be adapted
66
while in reset state. For example if a device has an irq input,
67
diff --git a/hw/core/resettable.c b/hw/core/resettable.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/hw/core/resettable.c
70
+++ b/hw/core/resettable.c
71
@@ -XXX,XX +XXX,XX @@ static void resettable_phase_exit(Object *obj, void *opaque, ResetType type)
72
resettable_child_foreach(rc, obj, resettable_phase_exit, NULL, type);
73
74
assert(s->count > 0);
75
- if (s->count == 1) {
76
+ if (--s->count == 0) {
77
trace_resettable_phase_exit_exec(obj, obj_typename, !!rc->phases.exit);
78
if (rc->phases.exit && !resettable_get_tr_func(rc, obj)) {
79
rc->phases.exit(obj);
80
}
81
- s->count = 0;
82
}
83
s->exit_phase_in_progress = false;
84
trace_resettable_phase_exit_end(obj, obj_typename, s->count);
85
--
31
--
86
2.25.1
32
2.19.1
87
33
88
34
diff view generated by jsdifflib
Deleted patch
1
The semantic difference between the deprecated device_legacy_reset()
2
function and the newer device_cold_reset() function is that the new
3
function resets both the device itself and any qbuses it owns,
4
whereas the legacy function resets just the device itself and nothing
5
else. In hyperv_synic_reset() we reset a SynICState, which has no
6
qbuses, so for this purpose the two functions behave identically and
7
we can stop using the deprecated one.
8
1
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
11
Message-id: 20221013171817.1447562-1-peter.maydell@linaro.org
12
---
13
hw/hyperv/hyperv.c | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/hyperv/hyperv.c
19
+++ b/hw/hyperv/hyperv.c
20
@@ -XXX,XX +XXX,XX @@ void hyperv_synic_reset(CPUState *cs)
21
SynICState *synic = get_synic(cs);
22
23
if (synic) {
24
- device_legacy_reset(DEVICE(synic));
25
+ device_cold_reset(DEVICE(synic));
26
}
27
}
28
29
--
30
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Axel Heider <axel.heider@hensoldt.net>
2
1
3
When running seL4 tests (https://docs.sel4.systems/projects/sel4test)
4
on the sabrelight platform, the timer tests fail. The arm/imx6 EPIT
5
timer interrupt does not fire properly, instead of a e.g. second in
6
can take up to a minute to finally see the interrupt.
7
8
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1263
9
10
Signed-off-by: Axel Heider <axel.heider@hensoldt.net>
11
Message-id: 166663118138.13362.1229967229046092876-0@git.sr.ht
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/timer/imx_epit.c | 9 +++++++--
16
1 file changed, 7 insertions(+), 2 deletions(-)
17
18
diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/timer/imx_epit.c
21
+++ b/hw/timer/imx_epit.c
22
@@ -XXX,XX +XXX,XX @@ static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
23
/* If IOVW bit is set then set the timer value */
24
ptimer_set_count(s->timer_reload, s->lr);
25
}
26
-
27
+ /*
28
+ * Commit the change to s->timer_reload, so it can propagate. Otherwise
29
+ * the timer interrupt may not fire properly. The commit must happen
30
+ * before calling imx_epit_reload_compare_timer(), which reads
31
+ * s->timer_reload internally again.
32
+ */
33
+ ptimer_transaction_commit(s->timer_reload);
34
imx_epit_reload_compare_timer(s);
35
ptimer_transaction_commit(s->timer_cmp);
36
- ptimer_transaction_commit(s->timer_reload);
37
break;
38
39
case 3: /* CMP */
40
--
41
2.25.1
diff view generated by jsdifflib
1
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
1
From: Prasad J Pandit <pjp@fedoraproject.org>
2
2
3
When the system reboots, the rng-seed that the FDT has should be
3
The high[31:28] bits of 'direction' and 'state' registers of
4
re-randomized, so that the new boot gets a new seed. Since the FDT is in
4
SA-1100/SA-1110 device are reserved. Setting them may lead to
5
the ROM region at this point, we add a hook right after the ROM has been
5
OOB 's->handler[]' array access issue. Mask off [31:28] bits to
6
added, so that we have a pointer to that copy of the FDT.
6
avoid it.
7
7
8
Cc: Peter Maydell <peter.maydell@linaro.org>
8
Reported-by: Moguofang <moguofang@huawei.com>
9
Cc: qemu-arm@nongnu.org
9
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
10
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
10
Message-id: 20181030114635.31232-1-ppandit@redhat.com
11
Message-id: 20221025004327.568476-5-Jason@zx2c4.com
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
13
---
15
hw/arm/boot.c | 2 ++
14
hw/arm/strongarm.c | 4 ++--
16
1 file changed, 2 insertions(+)
15
1 file changed, 2 insertions(+), 2 deletions(-)
17
16
18
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
17
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
19
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/boot.c
19
--- a/hw/arm/strongarm.c
21
+++ b/hw/arm/boot.c
20
+++ b/hw/arm/strongarm.c
22
@@ -XXX,XX +XXX,XX @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
21
@@ -XXX,XX +XXX,XX @@ static void strongarm_gpio_write(void *opaque, hwaddr offset,
23
* the DTB is copied again upon reset, even if addr points into RAM.
22
24
*/
23
switch (offset) {
25
rom_add_blob_fixed_as("dtb", fdt, size, addr, as);
24
case GPDR: /* GPIO Pin-Direction registers */
26
+ qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
25
- s->dir = value;
27
+ rom_ptr_for_as(as, addr, size));
26
+ s->dir = value & 0x0fffffff;
28
27
strongarm_gpio_handler_update(s);
29
g_free(fdt);
28
break;
29
30
case GPSR: /* GPIO Pin-Output Set registers */
31
- s->olevel |= value;
32
+ s->olevel |= value & 0x0fffffff;
33
strongarm_gpio_handler_update(s);
34
break;
30
35
31
--
36
--
32
2.25.1
37
2.19.1
38
39
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
Hoist the computation of the mmu_idx for the ptw up to
3
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
4
get_phys_addr_with_struct and get_phys_addr_twostage.
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
This removes the duplicate check for stage2 disabled
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
from the middle of the walk, performing it only once.
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Tested-by: Alex Bennée <alex.bennee@linaro.org>
11
Message-id: 20221024051851.3074715-3-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
8
---
14
target/arm/ptw.c | 71 ++++++++++++++++++++++++++++++++++++------------
9
hw/arm/xilinx_zynq.c | 2 +-
15
1 file changed, 54 insertions(+), 17 deletions(-)
10
1 file changed, 1 insertion(+), 1 deletion(-)
16
11
17
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
12
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/ptw.c
14
--- a/hw/arm/xilinx_zynq.c
20
+++ b/target/arm/ptw.c
15
+++ b/hw/arm/xilinx_zynq.c
21
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
22
17
busdev = SYS_BUS_DEVICE(dev);
23
typedef struct S1Translate {
18
sysbus_mmio_map(busdev, 0, 0xF8003000);
24
ARMMMUIdx in_mmu_idx;
19
sysbus_connect_irq(busdev, 0, pic[45-IRQ_OFFSET]); /* abort irq line */
25
+ ARMMMUIdx in_ptw_idx;
20
- for (n = 0; n < 8; ++n) { /* event irqs */
26
bool in_secure;
21
+ for (n = 0; n < ARRAY_SIZE(dma_irqs); ++n) { /* event irqs */
27
bool in_debug;
22
sysbus_connect_irq(busdev, n + 1, pic[dma_irqs[n] - IRQ_OFFSET]);
28
bool out_secure;
29
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
30
{
31
bool is_secure = ptw->in_secure;
32
ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
33
- ARMMMUIdx s2_mmu_idx = is_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
34
- bool s2_phys = false;
35
+ ARMMMUIdx s2_mmu_idx = ptw->in_ptw_idx;
36
uint8_t pte_attrs;
37
bool pte_secure;
38
39
- if (!arm_mmu_idx_is_stage1_of_2(mmu_idx)
40
- || regime_translation_disabled(env, s2_mmu_idx, is_secure)) {
41
- s2_mmu_idx = is_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS;
42
- s2_phys = true;
43
- }
44
-
45
if (unlikely(ptw->in_debug)) {
46
/*
47
* From gdbstub, do not use softmmu so that we don't modify the
48
* state of the cpu at all, including softmmu tlb contents.
49
*/
50
- if (s2_phys) {
51
- ptw->out_phys = addr;
52
- pte_attrs = 0;
53
- pte_secure = is_secure;
54
- } else {
55
+ if (regime_is_stage2(s2_mmu_idx)) {
56
S1Translate s2ptw = {
57
.in_mmu_idx = s2_mmu_idx,
58
+ .in_ptw_idx = is_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS,
59
.in_secure = is_secure,
60
.in_debug = true,
61
};
62
GetPhysAddrResult s2 = { };
63
+
64
if (!get_phys_addr_lpae(env, &s2ptw, addr, MMU_DATA_LOAD,
65
false, &s2, fi)) {
66
goto fail;
67
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
68
ptw->out_phys = s2.f.phys_addr;
69
pte_attrs = s2.cacheattrs.attrs;
70
pte_secure = s2.f.attrs.secure;
71
+ } else {
72
+ /* Regime is physical. */
73
+ ptw->out_phys = addr;
74
+ pte_attrs = 0;
75
+ pte_secure = is_secure;
76
}
77
ptw->out_host = NULL;
78
} else {
79
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
80
pte_secure = full->attrs.secure;
81
}
23
}
82
24
83
- if (!s2_phys) {
84
+ if (regime_is_stage2(s2_mmu_idx)) {
85
uint64_t hcr = arm_hcr_el2_eff_secstate(env, is_secure);
86
87
if ((hcr & HCR_PTW) && S2_attrs_are_device(hcr, pte_attrs)) {
88
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
89
descaddr |= (address >> (stride * (4 - level))) & indexmask;
90
descaddr &= ~7ULL;
91
nstable = extract32(tableattrs, 4, 1);
92
- ptw->in_secure = !nstable;
93
+ if (!nstable) {
94
+ /*
95
+ * Stage2_S -> Stage2 or Phys_S -> Phys_NS
96
+ * Assert that the non-secure idx are even, and relative order.
97
+ */
98
+ QEMU_BUILD_BUG_ON((ARMMMUIdx_Phys_NS & 1) != 0);
99
+ QEMU_BUILD_BUG_ON((ARMMMUIdx_Stage2 & 1) != 0);
100
+ QEMU_BUILD_BUG_ON(ARMMMUIdx_Phys_NS + 1 != ARMMMUIdx_Phys_S);
101
+ QEMU_BUILD_BUG_ON(ARMMMUIdx_Stage2 + 1 != ARMMMUIdx_Stage2_S);
102
+ ptw->in_ptw_idx &= ~1;
103
+ ptw->in_secure = false;
104
+ }
105
descriptor = arm_ldq_ptw(env, ptw, descaddr, fi);
106
if (fi->type != ARMFault_None) {
107
goto do_fault;
108
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
109
110
is_el0 = ptw->in_mmu_idx == ARMMMUIdx_Stage1_E0;
111
ptw->in_mmu_idx = s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
112
+ ptw->in_ptw_idx = s2walk_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS;
113
ptw->in_secure = s2walk_secure;
114
115
/*
116
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
117
ARMMMUFaultInfo *fi)
118
{
119
ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
120
- ARMMMUIdx s1_mmu_idx = stage_1_mmu_idx(mmu_idx);
121
bool is_secure = ptw->in_secure;
122
+ ARMMMUIdx s1_mmu_idx;
123
124
- if (mmu_idx != s1_mmu_idx) {
125
+ switch (mmu_idx) {
126
+ case ARMMMUIdx_Phys_S:
127
+ case ARMMMUIdx_Phys_NS:
128
+ /* Checking Phys early avoids special casing later vs regime_el. */
129
+ return get_phys_addr_disabled(env, address, access_type, mmu_idx,
130
+ is_secure, result, fi);
131
+
132
+ case ARMMMUIdx_Stage1_E0:
133
+ case ARMMMUIdx_Stage1_E1:
134
+ case ARMMMUIdx_Stage1_E1_PAN:
135
+ /* First stage lookup uses second stage for ptw. */
136
+ ptw->in_ptw_idx = is_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
137
+ break;
138
+
139
+ case ARMMMUIdx_E10_0:
140
+ s1_mmu_idx = ARMMMUIdx_Stage1_E0;
141
+ goto do_twostage;
142
+ case ARMMMUIdx_E10_1:
143
+ s1_mmu_idx = ARMMMUIdx_Stage1_E1;
144
+ goto do_twostage;
145
+ case ARMMMUIdx_E10_1_PAN:
146
+ s1_mmu_idx = ARMMMUIdx_Stage1_E1_PAN;
147
+ do_twostage:
148
/*
149
* Call ourselves recursively to do the stage 1 and then stage 2
150
* translations if mmu_idx is a two-stage regime, and EL2 present.
151
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
152
return get_phys_addr_twostage(env, ptw, address, access_type,
153
result, fi);
154
}
155
+ /* fall through */
156
+
157
+ default:
158
+ /* Single stage and second stage uses physical for ptw. */
159
+ ptw->in_ptw_idx = is_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS;
160
+ break;
161
}
162
163
/*
164
--
25
--
165
2.25.1
26
2.19.1
166
27
167
28
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The MMFR1 field may indicate support for hardware update of
3
When populating id registers from kvm, on a host that doesn't support
4
access flag alone, or access flag and dirty bit.
4
aarch32 mode at all, neither arm_div nor jazelle will be supported either.
5
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Tested-by: Alex Bennée <alex.bennee@linaro.org>
9
Message-id: 20181102102025.3546-1-richard.henderson@linaro.org
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20221024051851.3074715-4-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
12
---
11
target/arm/cpu.h | 10 ++++++++++
13
target/arm/cpu.h | 5 +++++
12
1 file changed, 10 insertions(+)
14
target/arm/cpu.c | 15 +++++++++++++--
15
2 files changed, 18 insertions(+), 2 deletions(-)
13
16
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
19
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_e0pd(const ARMISARegisters *id)
21
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
19
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, E0PD) != 0;
22
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1;
20
}
23
}
21
24
22
+static inline bool isar_feature_aa64_hafs(const ARMISARegisters *id)
25
+static inline bool isar_feature_aa64_aa32(const ARMISARegisters *id)
23
+{
26
+{
24
+ return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) != 0;
27
+ return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL0) >= 2;
25
+}
28
+}
26
+
29
+
27
+static inline bool isar_feature_aa64_hdbs(const ARMISARegisters *id)
30
static inline bool isar_feature_aa64_sve(const ARMISARegisters *id)
28
+{
31
{
29
+ return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) >= 2;
32
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0;
30
+}
33
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/cpu.c
36
+++ b/target/arm/cpu.c
37
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
38
CPUARMState *env = &cpu->env;
39
int pagebits;
40
Error *local_err = NULL;
41
+ bool no_aa32 = false;
42
43
/* If we needed to query the host kernel for the CPU features
44
* then it's possible that might have failed in the initfn, but
45
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
46
set_feature(env, ARM_FEATURE_V7VE);
47
}
48
}
31
+
49
+
32
static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id)
50
+ /*
33
{
51
+ * There exist AArch64 cpus without AArch32 support. When KVM
34
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0;
52
+ * queries ID_ISAR0_EL1 on such a host, the value is UNKNOWN.
53
+ * Similarly, we cannot check ID_AA64PFR0 without AArch64 support.
54
+ */
55
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
56
+ no_aa32 = !cpu_isar_feature(aa64_aa32, cpu);
57
+ }
58
+
59
if (arm_feature(env, ARM_FEATURE_V7VE)) {
60
/* v7 Virtualization Extensions. In real hardware this implies
61
* EL2 and also the presence of the Security Extensions.
62
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
63
* Presence of EL2 itself is ARM_FEATURE_EL2, and of the
64
* Security Extensions is ARM_FEATURE_EL3.
65
*/
66
- assert(cpu_isar_feature(arm_div, cpu));
67
+ assert(no_aa32 || cpu_isar_feature(arm_div, cpu));
68
set_feature(env, ARM_FEATURE_LPAE);
69
set_feature(env, ARM_FEATURE_V7);
70
}
71
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
72
if (arm_feature(env, ARM_FEATURE_V6)) {
73
set_feature(env, ARM_FEATURE_V5);
74
if (!arm_feature(env, ARM_FEATURE_M)) {
75
- assert(cpu_isar_feature(jazelle, cpu));
76
+ assert(no_aa32 || cpu_isar_feature(jazelle, cpu));
77
set_feature(env, ARM_FEATURE_AUXCR);
78
}
79
}
35
--
80
--
36
2.25.1
81
2.19.1
82
83
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Separate S1 translation from the actual lookup.
4
Will enable lpae hardware updates.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20221024051851.3074715-6-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/ptw.c | 41 ++++++++++++++++++++++-------------------
12
1 file changed, 22 insertions(+), 19 deletions(-)
13
14
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/ptw.c
17
+++ b/target/arm/ptw.c
18
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
19
}
20
21
/* All loads done in the course of a page table walk go through here. */
22
-static uint32_t arm_ldl_ptw(CPUARMState *env, S1Translate *ptw, hwaddr addr,
23
+static uint32_t arm_ldl_ptw(CPUARMState *env, S1Translate *ptw,
24
ARMMMUFaultInfo *fi)
25
{
26
CPUState *cs = env_cpu(env);
27
uint32_t data;
28
29
- if (!S1_ptw_translate(env, ptw, addr, fi)) {
30
- /* Failure. */
31
- assert(fi->s1ptw);
32
- return 0;
33
- }
34
-
35
if (likely(ptw->out_host)) {
36
/* Page tables are in RAM, and we have the host address. */
37
if (ptw->out_be) {
38
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_ldl_ptw(CPUARMState *env, S1Translate *ptw, hwaddr addr,
39
return data;
40
}
41
42
-static uint64_t arm_ldq_ptw(CPUARMState *env, S1Translate *ptw, hwaddr addr,
43
+static uint64_t arm_ldq_ptw(CPUARMState *env, S1Translate *ptw,
44
ARMMMUFaultInfo *fi)
45
{
46
CPUState *cs = env_cpu(env);
47
uint64_t data;
48
49
- if (!S1_ptw_translate(env, ptw, addr, fi)) {
50
- /* Failure. */
51
- assert(fi->s1ptw);
52
- return 0;
53
- }
54
-
55
if (likely(ptw->out_host)) {
56
/* Page tables are in RAM, and we have the host address. */
57
if (ptw->out_be) {
58
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v5(CPUARMState *env, S1Translate *ptw,
59
fi->type = ARMFault_Translation;
60
goto do_fault;
61
}
62
- desc = arm_ldl_ptw(env, ptw, table, fi);
63
+ if (!S1_ptw_translate(env, ptw, table, fi)) {
64
+ goto do_fault;
65
+ }
66
+ desc = arm_ldl_ptw(env, ptw, fi);
67
if (fi->type != ARMFault_None) {
68
goto do_fault;
69
}
70
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v5(CPUARMState *env, S1Translate *ptw,
71
/* Fine pagetable. */
72
table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
73
}
74
- desc = arm_ldl_ptw(env, ptw, table, fi);
75
+ if (!S1_ptw_translate(env, ptw, table, fi)) {
76
+ goto do_fault;
77
+ }
78
+ desc = arm_ldl_ptw(env, ptw, fi);
79
if (fi->type != ARMFault_None) {
80
goto do_fault;
81
}
82
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v6(CPUARMState *env, S1Translate *ptw,
83
fi->type = ARMFault_Translation;
84
goto do_fault;
85
}
86
- desc = arm_ldl_ptw(env, ptw, table, fi);
87
+ if (!S1_ptw_translate(env, ptw, table, fi)) {
88
+ goto do_fault;
89
+ }
90
+ desc = arm_ldl_ptw(env, ptw, fi);
91
if (fi->type != ARMFault_None) {
92
goto do_fault;
93
}
94
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v6(CPUARMState *env, S1Translate *ptw,
95
ns = extract32(desc, 3, 1);
96
/* Lookup l2 entry. */
97
table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
98
- desc = arm_ldl_ptw(env, ptw, table, fi);
99
+ if (!S1_ptw_translate(env, ptw, table, fi)) {
100
+ goto do_fault;
101
+ }
102
+ desc = arm_ldl_ptw(env, ptw, fi);
103
if (fi->type != ARMFault_None) {
104
goto do_fault;
105
}
106
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
107
ptw->in_ptw_idx &= ~1;
108
ptw->in_secure = false;
109
}
110
- descriptor = arm_ldq_ptw(env, ptw, descaddr, fi);
111
+ if (!S1_ptw_translate(env, ptw, descaddr, fi)) {
112
+ goto do_fault;
113
+ }
114
+ descriptor = arm_ldq_ptw(env, ptw, fi);
115
if (fi->type != ARMFault_None) {
116
goto do_fault;
117
}
118
--
119
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
The unconditional loop was used both to iterate over levels
4
and to control parsing of attributes. Use an explicit goto
5
in both cases.
6
7
While this appears less clean for iterating over levels, we
8
will need to jump back into the middle of this loop for
9
atomic updates, which is even uglier.
10
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20221024051851.3074715-8-richard.henderson@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
target/arm/ptw.c | 192 +++++++++++++++++++++++------------------------
17
1 file changed, 96 insertions(+), 96 deletions(-)
18
19
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/ptw.c
22
+++ b/target/arm/ptw.c
23
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
24
uint64_t descaddrmask;
25
bool aarch64 = arm_el_is_aa64(env, el);
26
bool guarded = false;
27
+ uint64_t descriptor;
28
+ bool nstable;
29
30
/* TODO: This code does not support shareability levels. */
31
if (aarch64) {
32
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
33
* bits at each step.
34
*/
35
tableattrs = is_secure ? 0 : (1 << 4);
36
- for (;;) {
37
- uint64_t descriptor;
38
- bool nstable;
39
-
40
- descaddr |= (address >> (stride * (4 - level))) & indexmask;
41
- descaddr &= ~7ULL;
42
- nstable = extract32(tableattrs, 4, 1);
43
- if (!nstable) {
44
- /*
45
- * Stage2_S -> Stage2 or Phys_S -> Phys_NS
46
- * Assert that the non-secure idx are even, and relative order.
47
- */
48
- QEMU_BUILD_BUG_ON((ARMMMUIdx_Phys_NS & 1) != 0);
49
- QEMU_BUILD_BUG_ON((ARMMMUIdx_Stage2 & 1) != 0);
50
- QEMU_BUILD_BUG_ON(ARMMMUIdx_Phys_NS + 1 != ARMMMUIdx_Phys_S);
51
- QEMU_BUILD_BUG_ON(ARMMMUIdx_Stage2 + 1 != ARMMMUIdx_Stage2_S);
52
- ptw->in_ptw_idx &= ~1;
53
- ptw->in_secure = false;
54
- }
55
- if (!S1_ptw_translate(env, ptw, descaddr, fi)) {
56
- goto do_fault;
57
- }
58
- descriptor = arm_ldq_ptw(env, ptw, fi);
59
- if (fi->type != ARMFault_None) {
60
- goto do_fault;
61
- }
62
-
63
- if (!(descriptor & 1) ||
64
- (!(descriptor & 2) && (level == 3))) {
65
- /* Invalid, or the Reserved level 3 encoding */
66
- goto do_fault;
67
- }
68
-
69
- descaddr = descriptor & descaddrmask;
70
71
+ next_level:
72
+ descaddr |= (address >> (stride * (4 - level))) & indexmask;
73
+ descaddr &= ~7ULL;
74
+ nstable = extract32(tableattrs, 4, 1);
75
+ if (!nstable) {
76
/*
77
- * For FEAT_LPA and PS=6, bits [51:48] of descaddr are in [15:12]
78
- * of descriptor. For FEAT_LPA2 and effective DS, bits [51:50] of
79
- * descaddr are in [9:8]. Otherwise, if descaddr is out of range,
80
- * raise AddressSizeFault.
81
+ * Stage2_S -> Stage2 or Phys_S -> Phys_NS
82
+ * Assert that the non-secure idx are even, and relative order.
83
*/
84
- if (outputsize > 48) {
85
- if (param.ds) {
86
- descaddr |= extract64(descriptor, 8, 2) << 50;
87
- } else {
88
- descaddr |= extract64(descriptor, 12, 4) << 48;
89
- }
90
- } else if (descaddr >> outputsize) {
91
- fault_type = ARMFault_AddressSize;
92
- goto do_fault;
93
- }
94
-
95
- if ((descriptor & 2) && (level < 3)) {
96
- /*
97
- * Table entry. The top five bits are attributes which may
98
- * propagate down through lower levels of the table (and
99
- * which are all arranged so that 0 means "no effect", so
100
- * we can gather them up by ORing in the bits at each level).
101
- */
102
- tableattrs |= extract64(descriptor, 59, 5);
103
- level++;
104
- indexmask = indexmask_grainsize;
105
- continue;
106
- }
107
- /*
108
- * Block entry at level 1 or 2, or page entry at level 3.
109
- * These are basically the same thing, although the number
110
- * of bits we pull in from the vaddr varies. Note that although
111
- * descaddrmask masks enough of the low bits of the descriptor
112
- * to give a correct page or table address, the address field
113
- * in a block descriptor is smaller; so we need to explicitly
114
- * clear the lower bits here before ORing in the low vaddr bits.
115
- */
116
- page_size = (1ULL << ((stride * (4 - level)) + 3));
117
- descaddr &= ~(hwaddr)(page_size - 1);
118
- descaddr |= (address & (page_size - 1));
119
- /* Extract attributes from the descriptor */
120
- attrs = extract64(descriptor, 2, 10)
121
- | (extract64(descriptor, 52, 12) << 10);
122
-
123
- if (regime_is_stage2(mmu_idx)) {
124
- /* Stage 2 table descriptors do not include any attribute fields */
125
- break;
126
- }
127
- /* Merge in attributes from table descriptors */
128
- attrs |= nstable << 3; /* NS */
129
- guarded = extract64(descriptor, 50, 1); /* GP */
130
- if (param.hpd) {
131
- /* HPD disables all the table attributes except NSTable. */
132
- break;
133
- }
134
- attrs |= extract32(tableattrs, 0, 2) << 11; /* XN, PXN */
135
- /*
136
- * The sense of AP[1] vs APTable[0] is reversed, as APTable[0] == 1
137
- * means "force PL1 access only", which means forcing AP[1] to 0.
138
- */
139
- attrs &= ~(extract32(tableattrs, 2, 1) << 4); /* !APT[0] => AP[1] */
140
- attrs |= extract32(tableattrs, 3, 1) << 5; /* APT[1] => AP[2] */
141
- break;
142
+ QEMU_BUILD_BUG_ON((ARMMMUIdx_Phys_NS & 1) != 0);
143
+ QEMU_BUILD_BUG_ON((ARMMMUIdx_Stage2 & 1) != 0);
144
+ QEMU_BUILD_BUG_ON(ARMMMUIdx_Phys_NS + 1 != ARMMMUIdx_Phys_S);
145
+ QEMU_BUILD_BUG_ON(ARMMMUIdx_Stage2 + 1 != ARMMMUIdx_Stage2_S);
146
+ ptw->in_ptw_idx &= ~1;
147
+ ptw->in_secure = false;
148
}
149
+ if (!S1_ptw_translate(env, ptw, descaddr, fi)) {
150
+ goto do_fault;
151
+ }
152
+ descriptor = arm_ldq_ptw(env, ptw, fi);
153
+ if (fi->type != ARMFault_None) {
154
+ goto do_fault;
155
+ }
156
+
157
+ if (!(descriptor & 1) || (!(descriptor & 2) && (level == 3))) {
158
+ /* Invalid, or the Reserved level 3 encoding */
159
+ goto do_fault;
160
+ }
161
+
162
+ descaddr = descriptor & descaddrmask;
163
+
164
+ /*
165
+ * For FEAT_LPA and PS=6, bits [51:48] of descaddr are in [15:12]
166
+ * of descriptor. For FEAT_LPA2 and effective DS, bits [51:50] of
167
+ * descaddr are in [9:8]. Otherwise, if descaddr is out of range,
168
+ * raise AddressSizeFault.
169
+ */
170
+ if (outputsize > 48) {
171
+ if (param.ds) {
172
+ descaddr |= extract64(descriptor, 8, 2) << 50;
173
+ } else {
174
+ descaddr |= extract64(descriptor, 12, 4) << 48;
175
+ }
176
+ } else if (descaddr >> outputsize) {
177
+ fault_type = ARMFault_AddressSize;
178
+ goto do_fault;
179
+ }
180
+
181
+ if ((descriptor & 2) && (level < 3)) {
182
+ /*
183
+ * Table entry. The top five bits are attributes which may
184
+ * propagate down through lower levels of the table (and
185
+ * which are all arranged so that 0 means "no effect", so
186
+ * we can gather them up by ORing in the bits at each level).
187
+ */
188
+ tableattrs |= extract64(descriptor, 59, 5);
189
+ level++;
190
+ indexmask = indexmask_grainsize;
191
+ goto next_level;
192
+ }
193
+
194
+ /*
195
+ * Block entry at level 1 or 2, or page entry at level 3.
196
+ * These are basically the same thing, although the number
197
+ * of bits we pull in from the vaddr varies. Note that although
198
+ * descaddrmask masks enough of the low bits of the descriptor
199
+ * to give a correct page or table address, the address field
200
+ * in a block descriptor is smaller; so we need to explicitly
201
+ * clear the lower bits here before ORing in the low vaddr bits.
202
+ */
203
+ page_size = (1ULL << ((stride * (4 - level)) + 3));
204
+ descaddr &= ~(hwaddr)(page_size - 1);
205
+ descaddr |= (address & (page_size - 1));
206
+ /* Extract attributes from the descriptor */
207
+ attrs = extract64(descriptor, 2, 10)
208
+ | (extract64(descriptor, 52, 12) << 10);
209
+
210
+ if (regime_is_stage2(mmu_idx)) {
211
+ /* Stage 2 table descriptors do not include any attribute fields */
212
+ goto skip_attrs;
213
+ }
214
+ /* Merge in attributes from table descriptors */
215
+ attrs |= nstable << 3; /* NS */
216
+ guarded = extract64(descriptor, 50, 1); /* GP */
217
+ if (param.hpd) {
218
+ /* HPD disables all the table attributes except NSTable. */
219
+ goto skip_attrs;
220
+ }
221
+ attrs |= extract32(tableattrs, 0, 2) << 11; /* XN, PXN */
222
+ /*
223
+ * The sense of AP[1] vs APTable[0] is reversed, as APTable[0] == 1
224
+ * means "force PL1 access only", which means forcing AP[1] to 0.
225
+ */
226
+ attrs &= ~(extract32(tableattrs, 2, 1) << 4); /* !APT[0] => AP[1] */
227
+ attrs |= extract32(tableattrs, 3, 1) << 5; /* APT[1] => AP[2] */
228
+ skip_attrs:
229
+
230
/*
231
* Here descaddr is the final physical address, and attributes
232
* are all in attrs.
233
--
234
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Always overriding fi->type was incorrect, as we would not properly
4
propagate the fault type from S1_ptw_translate, or arm_ldq_ptw.
5
Simplify things by providing a new label for a translation fault.
6
For other faults, store into fi directly.
7
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Message-id: 20221024051851.3074715-9-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/ptw.c | 31 +++++++++++++------------------
15
1 file changed, 13 insertions(+), 18 deletions(-)
16
17
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/ptw.c
20
+++ b/target/arm/ptw.c
21
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
22
ARMCPU *cpu = env_archcpu(env);
23
ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
24
bool is_secure = ptw->in_secure;
25
- /* Read an LPAE long-descriptor translation table. */
26
- ARMFaultType fault_type = ARMFault_Translation;
27
uint32_t level;
28
ARMVAParameters param;
29
uint64_t ttbr;
30
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
31
* so our choice is to always raise the fault.
32
*/
33
if (param.tsz_oob) {
34
- fault_type = ARMFault_Translation;
35
- goto do_fault;
36
+ goto do_translation_fault;
37
}
38
39
addrsize = 64 - 8 * param.tbi;
40
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
41
addrsize - inputsize);
42
if (-top_bits != param.select) {
43
/* The gap between the two regions is a Translation fault */
44
- fault_type = ARMFault_Translation;
45
- goto do_fault;
46
+ goto do_translation_fault;
47
}
48
}
49
50
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
51
* Translation table walk disabled => Translation fault on TLB miss
52
* Note: This is always 0 on 64-bit EL2 and EL3.
53
*/
54
- goto do_fault;
55
+ goto do_translation_fault;
56
}
57
58
if (!regime_is_stage2(mmu_idx)) {
59
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
60
if (param.ds && stride == 9 && sl2) {
61
if (sl0 != 0) {
62
level = 0;
63
- fault_type = ARMFault_Translation;
64
- goto do_fault;
65
+ goto do_translation_fault;
66
}
67
startlevel = -1;
68
} else if (!aarch64 || stride == 9) {
69
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
70
ok = check_s2_mmu_setup(cpu, aarch64, startlevel,
71
inputsize, stride, outputsize);
72
if (!ok) {
73
- fault_type = ARMFault_Translation;
74
- goto do_fault;
75
+ goto do_translation_fault;
76
}
77
level = startlevel;
78
}
79
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
80
descaddr |= extract64(ttbr, 2, 4) << 48;
81
} else if (descaddr >> outputsize) {
82
level = 0;
83
- fault_type = ARMFault_AddressSize;
84
+ fi->type = ARMFault_AddressSize;
85
goto do_fault;
86
}
87
88
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
89
90
if (!(descriptor & 1) || (!(descriptor & 2) && (level == 3))) {
91
/* Invalid, or the Reserved level 3 encoding */
92
- goto do_fault;
93
+ goto do_translation_fault;
94
}
95
96
descaddr = descriptor & descaddrmask;
97
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
98
descaddr |= extract64(descriptor, 12, 4) << 48;
99
}
100
} else if (descaddr >> outputsize) {
101
- fault_type = ARMFault_AddressSize;
102
+ fi->type = ARMFault_AddressSize;
103
goto do_fault;
104
}
105
106
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
107
* Here descaddr is the final physical address, and attributes
108
* are all in attrs.
109
*/
110
- fault_type = ARMFault_AccessFlag;
111
if ((attrs & (1 << 8)) == 0) {
112
/* Access flag */
113
+ fi->type = ARMFault_AccessFlag;
114
goto do_fault;
115
}
116
117
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
118
result->f.prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn);
119
}
120
121
- fault_type = ARMFault_Permission;
122
if (!(result->f.prot & (1 << access_type))) {
123
+ fi->type = ARMFault_Permission;
124
goto do_fault;
125
}
126
127
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
128
result->f.lg_page_size = ctz64(page_size);
129
return false;
130
131
-do_fault:
132
- fi->type = fault_type;
133
+ do_translation_fault:
134
+ fi->type = ARMFault_Translation;
135
+ do_fault:
136
fi->level = level;
137
/* Tag the error as S2 for failed S1 PTW at S2 or ordinary S2. */
138
fi->stage2 = fi->s1ptw || regime_is_stage2(mmu_idx);
139
--
140
2.25.1
141
142
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Leave the upper and lower attributes in the place they originate
4
from in the descriptor. Shifting them around is confusing, since
5
one cannot read the bit numbers out of the manual. Also, new
6
attributes have been added which would alter the shifts.
7
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Message-id: 20221024051851.3074715-10-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/ptw.c | 31 +++++++++++++++----------------
15
1 file changed, 15 insertions(+), 16 deletions(-)
16
17
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/ptw.c
20
+++ b/target/arm/ptw.c
21
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
22
hwaddr descaddr, indexmask, indexmask_grainsize;
23
uint32_t tableattrs;
24
target_ulong page_size;
25
- uint32_t attrs;
26
+ uint64_t attrs;
27
int32_t stride;
28
int addrsize, inputsize, outputsize;
29
uint64_t tcr = regime_tcr(env, mmu_idx);
30
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
31
descaddr &= ~(hwaddr)(page_size - 1);
32
descaddr |= (address & (page_size - 1));
33
/* Extract attributes from the descriptor */
34
- attrs = extract64(descriptor, 2, 10)
35
- | (extract64(descriptor, 52, 12) << 10);
36
+ attrs = descriptor & (MAKE_64BIT_MASK(2, 10) | MAKE_64BIT_MASK(52, 12));
37
38
if (regime_is_stage2(mmu_idx)) {
39
/* Stage 2 table descriptors do not include any attribute fields */
40
goto skip_attrs;
41
}
42
/* Merge in attributes from table descriptors */
43
- attrs |= nstable << 3; /* NS */
44
+ attrs |= nstable << 5; /* NS */
45
guarded = extract64(descriptor, 50, 1); /* GP */
46
if (param.hpd) {
47
/* HPD disables all the table attributes except NSTable. */
48
goto skip_attrs;
49
}
50
- attrs |= extract32(tableattrs, 0, 2) << 11; /* XN, PXN */
51
+ attrs |= extract64(tableattrs, 0, 2) << 53; /* XN, PXN */
52
/*
53
* The sense of AP[1] vs APTable[0] is reversed, as APTable[0] == 1
54
* means "force PL1 access only", which means forcing AP[1] to 0.
55
*/
56
- attrs &= ~(extract32(tableattrs, 2, 1) << 4); /* !APT[0] => AP[1] */
57
- attrs |= extract32(tableattrs, 3, 1) << 5; /* APT[1] => AP[2] */
58
+ attrs &= ~(extract64(tableattrs, 2, 1) << 6); /* !APT[0] => AP[1] */
59
+ attrs |= extract32(tableattrs, 3, 1) << 7; /* APT[1] => AP[2] */
60
skip_attrs:
61
62
/*
63
* Here descaddr is the final physical address, and attributes
64
* are all in attrs.
65
*/
66
- if ((attrs & (1 << 8)) == 0) {
67
+ if ((attrs & (1 << 10)) == 0) {
68
/* Access flag */
69
fi->type = ARMFault_AccessFlag;
70
goto do_fault;
71
}
72
73
- ap = extract32(attrs, 4, 2);
74
+ ap = extract32(attrs, 6, 2);
75
76
if (regime_is_stage2(mmu_idx)) {
77
ns = mmu_idx == ARMMMUIdx_Stage2;
78
- xn = extract32(attrs, 11, 2);
79
+ xn = extract64(attrs, 53, 2);
80
result->f.prot = get_S2prot(env, ap, xn, s1_is_el0);
81
} else {
82
- ns = extract32(attrs, 3, 1);
83
- xn = extract32(attrs, 12, 1);
84
- pxn = extract32(attrs, 11, 1);
85
+ ns = extract32(attrs, 5, 1);
86
+ xn = extract64(attrs, 54, 1);
87
+ pxn = extract64(attrs, 53, 1);
88
result->f.prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn);
89
}
90
91
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
92
93
if (regime_is_stage2(mmu_idx)) {
94
result->cacheattrs.is_s2_format = true;
95
- result->cacheattrs.attrs = extract32(attrs, 0, 4);
96
+ result->cacheattrs.attrs = extract32(attrs, 2, 4);
97
} else {
98
/* Index into MAIR registers for cache attributes */
99
- uint8_t attrindx = extract32(attrs, 0, 3);
100
+ uint8_t attrindx = extract32(attrs, 2, 3);
101
uint64_t mair = env->cp15.mair_el[regime_el(env, mmu_idx)];
102
assert(attrindx <= 7);
103
result->cacheattrs.is_s2_format = false;
104
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
105
if (param.ds) {
106
result->cacheattrs.shareability = param.sh;
107
} else {
108
- result->cacheattrs.shareability = extract32(attrs, 6, 2);
109
+ result->cacheattrs.shareability = extract32(attrs, 8, 2);
110
}
111
112
result->f.phys_addr = descaddr;
113
--
114
2.25.1
115
116
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Both GP and DBM are in the upper attribute block.
4
Extend the computation of attrs to include them,
5
then simplify the setting of guarded.
6
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Message-id: 20221024051851.3074715-11-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/ptw.c | 6 ++----
15
1 file changed, 2 insertions(+), 4 deletions(-)
16
17
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/ptw.c
20
+++ b/target/arm/ptw.c
21
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
22
uint32_t el = regime_el(env, mmu_idx);
23
uint64_t descaddrmask;
24
bool aarch64 = arm_el_is_aa64(env, el);
25
- bool guarded = false;
26
uint64_t descriptor;
27
bool nstable;
28
29
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
30
descaddr &= ~(hwaddr)(page_size - 1);
31
descaddr |= (address & (page_size - 1));
32
/* Extract attributes from the descriptor */
33
- attrs = descriptor & (MAKE_64BIT_MASK(2, 10) | MAKE_64BIT_MASK(52, 12));
34
+ attrs = descriptor & (MAKE_64BIT_MASK(2, 10) | MAKE_64BIT_MASK(50, 14));
35
36
if (regime_is_stage2(mmu_idx)) {
37
/* Stage 2 table descriptors do not include any attribute fields */
38
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
39
}
40
/* Merge in attributes from table descriptors */
41
attrs |= nstable << 5; /* NS */
42
- guarded = extract64(descriptor, 50, 1); /* GP */
43
if (param.hpd) {
44
/* HPD disables all the table attributes except NSTable. */
45
goto skip_attrs;
46
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
47
48
/* When in aarch64 mode, and BTI is enabled, remember GP in the TLB. */
49
if (aarch64 && cpu_isar_feature(aa64_bti, cpu)) {
50
- result->f.guarded = guarded;
51
+ result->f.guarded = extract64(attrs, 50, 1); /* GP */
52
}
53
54
if (regime_is_stage2(mmu_idx)) {
55
--
56
2.25.1
57
58
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Replace some gotos with some nested if statements.
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Message-id: 20221024051851.3074715-12-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/ptw.c | 34 ++++++++++++++++------------------
11
1 file changed, 16 insertions(+), 18 deletions(-)
12
13
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/ptw.c
16
+++ b/target/arm/ptw.c
17
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
18
page_size = (1ULL << ((stride * (4 - level)) + 3));
19
descaddr &= ~(hwaddr)(page_size - 1);
20
descaddr |= (address & (page_size - 1));
21
- /* Extract attributes from the descriptor */
22
- attrs = descriptor & (MAKE_64BIT_MASK(2, 10) | MAKE_64BIT_MASK(50, 14));
23
24
- if (regime_is_stage2(mmu_idx)) {
25
- /* Stage 2 table descriptors do not include any attribute fields */
26
- goto skip_attrs;
27
- }
28
- /* Merge in attributes from table descriptors */
29
- attrs |= nstable << 5; /* NS */
30
- if (param.hpd) {
31
- /* HPD disables all the table attributes except NSTable. */
32
- goto skip_attrs;
33
- }
34
- attrs |= extract64(tableattrs, 0, 2) << 53; /* XN, PXN */
35
/*
36
- * The sense of AP[1] vs APTable[0] is reversed, as APTable[0] == 1
37
- * means "force PL1 access only", which means forcing AP[1] to 0.
38
+ * Extract attributes from the descriptor, and apply table descriptors.
39
+ * Stage 2 table descriptors do not include any attribute fields.
40
+ * HPD disables all the table attributes except NSTable.
41
*/
42
- attrs &= ~(extract64(tableattrs, 2, 1) << 6); /* !APT[0] => AP[1] */
43
- attrs |= extract32(tableattrs, 3, 1) << 7; /* APT[1] => AP[2] */
44
- skip_attrs:
45
+ attrs = descriptor & (MAKE_64BIT_MASK(2, 10) | MAKE_64BIT_MASK(50, 14));
46
+ if (!regime_is_stage2(mmu_idx)) {
47
+ attrs |= nstable << 5; /* NS */
48
+ if (!param.hpd) {
49
+ attrs |= extract64(tableattrs, 0, 2) << 53; /* XN, PXN */
50
+ /*
51
+ * The sense of AP[1] vs APTable[0] is reversed, as APTable[0] == 1
52
+ * means "force PL1 access only", which means forcing AP[1] to 0.
53
+ */
54
+ attrs &= ~(extract64(tableattrs, 2, 1) << 6); /* !APT[0] => AP[1] */
55
+ attrs |= extract32(tableattrs, 3, 1) << 7; /* APT[1] => AP[2] */
56
+ }
57
+ }
58
59
/*
60
* Here descaddr is the final physical address, and attributes
61
--
62
2.25.1
63
64
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Perform the atomic update for hardware management of the access flag.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20221024051851.3074715-13-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
docs/system/arm/emulation.rst | 1 +
11
target/arm/cpu64.c | 1 +
12
target/arm/ptw.c | 176 +++++++++++++++++++++++++++++-----
13
3 files changed, 156 insertions(+), 22 deletions(-)
14
15
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
16
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/system/arm/emulation.rst
18
+++ b/docs/system/arm/emulation.rst
19
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
20
- FEAT_FlagM (Flag manipulation instructions v2)
21
- FEAT_FlagM2 (Enhancements to flag manipulation instructions)
22
- FEAT_GTG (Guest translation granule size)
23
+- FEAT_HAFDBS (Hardware management of the access flag and dirty bit state)
24
- FEAT_HCX (Support for the HCRX_EL2 register)
25
- FEAT_HPDS (Hierarchical permission disables)
26
- FEAT_I8MM (AArch64 Int8 matrix multiplication instructions)
27
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/cpu64.c
30
+++ b/target/arm/cpu64.c
31
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
32
cpu->isar.id_aa64mmfr0 = t;
33
34
t = cpu->isar.id_aa64mmfr1;
35
+ t = FIELD_DP64(t, ID_AA64MMFR1, HAFDBS, 1); /* FEAT_HAFDBS, AF only */
36
t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* FEAT_VMID16 */
37
t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1); /* FEAT_VHE */
38
t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* FEAT_HPDS */
39
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/ptw.c
42
+++ b/target/arm/ptw.c
43
@@ -XXX,XX +XXX,XX @@ typedef struct S1Translate {
44
bool in_secure;
45
bool in_debug;
46
bool out_secure;
47
+ bool out_rw;
48
bool out_be;
49
+ hwaddr out_virt;
50
hwaddr out_phys;
51
void *out_host;
52
} S1Translate;
53
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
54
uint8_t pte_attrs;
55
bool pte_secure;
56
57
+ ptw->out_virt = addr;
58
+
59
if (unlikely(ptw->in_debug)) {
60
/*
61
* From gdbstub, do not use softmmu so that we don't modify the
62
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
63
pte_secure = is_secure;
64
}
65
ptw->out_host = NULL;
66
+ ptw->out_rw = false;
67
} else {
68
CPUTLBEntryFull *full;
69
int flags;
70
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
71
goto fail;
72
}
73
ptw->out_phys = full->phys_addr;
74
+ ptw->out_rw = full->prot & PROT_WRITE;
75
pte_attrs = full->pte_attrs;
76
pte_secure = full->attrs.secure;
77
}
78
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_ldl_ptw(CPUARMState *env, S1Translate *ptw,
79
ARMMMUFaultInfo *fi)
80
{
81
CPUState *cs = env_cpu(env);
82
+ void *host = ptw->out_host;
83
uint32_t data;
84
85
- if (likely(ptw->out_host)) {
86
+ if (likely(host)) {
87
/* Page tables are in RAM, and we have the host address. */
88
+ data = qatomic_read((uint32_t *)host);
89
if (ptw->out_be) {
90
- data = ldl_be_p(ptw->out_host);
91
+ data = be32_to_cpu(data);
92
} else {
93
- data = ldl_le_p(ptw->out_host);
94
+ data = le32_to_cpu(data);
95
}
96
} else {
97
/* Page tables are in MMIO. */
98
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_ldq_ptw(CPUARMState *env, S1Translate *ptw,
99
ARMMMUFaultInfo *fi)
100
{
101
CPUState *cs = env_cpu(env);
102
+ void *host = ptw->out_host;
103
uint64_t data;
104
105
- if (likely(ptw->out_host)) {
106
+ if (likely(host)) {
107
/* Page tables are in RAM, and we have the host address. */
108
+#ifdef CONFIG_ATOMIC64
109
+ data = qatomic_read__nocheck((uint64_t *)host);
110
if (ptw->out_be) {
111
- data = ldq_be_p(ptw->out_host);
112
+ data = be64_to_cpu(data);
113
} else {
114
- data = ldq_le_p(ptw->out_host);
115
+ data = le64_to_cpu(data);
116
}
117
+#else
118
+ if (ptw->out_be) {
119
+ data = ldq_be_p(host);
120
+ } else {
121
+ data = ldq_le_p(host);
122
+ }
123
+#endif
124
} else {
125
/* Page tables are in MMIO. */
126
MemTxAttrs attrs = { .secure = ptw->out_secure };
127
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_ldq_ptw(CPUARMState *env, S1Translate *ptw,
128
return data;
129
}
130
131
+static uint64_t arm_casq_ptw(CPUARMState *env, uint64_t old_val,
132
+ uint64_t new_val, S1Translate *ptw,
133
+ ARMMMUFaultInfo *fi)
134
+{
135
+ uint64_t cur_val;
136
+ void *host = ptw->out_host;
137
+
138
+ if (unlikely(!host)) {
139
+ fi->type = ARMFault_UnsuppAtomicUpdate;
140
+ fi->s1ptw = true;
141
+ return 0;
142
+ }
143
+
144
+ /*
145
+ * Raising a stage2 Protection fault for an atomic update to a read-only
146
+ * page is delayed until it is certain that there is a change to make.
147
+ */
148
+ if (unlikely(!ptw->out_rw)) {
149
+ int flags;
150
+ void *discard;
151
+
152
+ env->tlb_fi = fi;
153
+ flags = probe_access_flags(env, ptw->out_virt, MMU_DATA_STORE,
154
+ arm_to_core_mmu_idx(ptw->in_ptw_idx),
155
+ true, &discard, 0);
156
+ env->tlb_fi = NULL;
157
+
158
+ if (unlikely(flags & TLB_INVALID_MASK)) {
159
+ assert(fi->type != ARMFault_None);
160
+ fi->s2addr = ptw->out_virt;
161
+ fi->stage2 = true;
162
+ fi->s1ptw = true;
163
+ fi->s1ns = !ptw->in_secure;
164
+ return 0;
165
+ }
166
+
167
+ /* In case CAS mismatches and we loop, remember writability. */
168
+ ptw->out_rw = true;
169
+ }
170
+
171
+#ifdef CONFIG_ATOMIC64
172
+ if (ptw->out_be) {
173
+ old_val = cpu_to_be64(old_val);
174
+ new_val = cpu_to_be64(new_val);
175
+ cur_val = qatomic_cmpxchg__nocheck((uint64_t *)host, old_val, new_val);
176
+ cur_val = be64_to_cpu(cur_val);
177
+ } else {
178
+ old_val = cpu_to_le64(old_val);
179
+ new_val = cpu_to_le64(new_val);
180
+ cur_val = qatomic_cmpxchg__nocheck((uint64_t *)host, old_val, new_val);
181
+ cur_val = le64_to_cpu(cur_val);
182
+ }
183
+#else
184
+ /*
185
+ * We can't support the full 64-bit atomic cmpxchg on the host.
186
+ * Because this is only used for FEAT_HAFDBS, which is only for AA64,
187
+ * we know that TCG_OVERSIZED_GUEST is set, which means that we are
188
+ * running in round-robin mode and could only race with dma i/o.
189
+ */
190
+#ifndef TCG_OVERSIZED_GUEST
191
+# error "Unexpected configuration"
192
+#endif
193
+ bool locked = qemu_mutex_iothread_locked();
194
+ if (!locked) {
195
+ qemu_mutex_lock_iothread();
196
+ }
197
+ if (ptw->out_be) {
198
+ cur_val = ldq_be_p(host);
199
+ if (cur_val == old_val) {
200
+ stq_be_p(host, new_val);
201
+ }
202
+ } else {
203
+ cur_val = ldq_le_p(host);
204
+ if (cur_val == old_val) {
205
+ stq_le_p(host, new_val);
206
+ }
207
+ }
208
+ if (!locked) {
209
+ qemu_mutex_unlock_iothread();
210
+ }
211
+#endif
212
+
213
+ return cur_val;
214
+}
215
+
216
static bool get_level1_table_address(CPUARMState *env, ARMMMUIdx mmu_idx,
217
uint32_t *table, uint32_t address)
218
{
219
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
220
uint32_t el = regime_el(env, mmu_idx);
221
uint64_t descaddrmask;
222
bool aarch64 = arm_el_is_aa64(env, el);
223
- uint64_t descriptor;
224
+ uint64_t descriptor, new_descriptor;
225
bool nstable;
226
227
/* TODO: This code does not support shareability levels. */
228
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
229
if (fi->type != ARMFault_None) {
230
goto do_fault;
231
}
232
+ new_descriptor = descriptor;
233
234
+ restart_atomic_update:
235
if (!(descriptor & 1) || (!(descriptor & 2) && (level == 3))) {
236
/* Invalid, or the Reserved level 3 encoding */
237
goto do_translation_fault;
238
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
239
* to give a correct page or table address, the address field
240
* in a block descriptor is smaller; so we need to explicitly
241
* clear the lower bits here before ORing in the low vaddr bits.
242
+ *
243
+ * Afterward, descaddr is the final physical address.
244
*/
245
page_size = (1ULL << ((stride * (4 - level)) + 3));
246
descaddr &= ~(hwaddr)(page_size - 1);
247
descaddr |= (address & (page_size - 1));
248
249
+ if (likely(!ptw->in_debug)) {
250
+ /*
251
+ * Access flag.
252
+ * If HA is enabled, prepare to update the descriptor below.
253
+ * Otherwise, pass the access fault on to software.
254
+ */
255
+ if (!(descriptor & (1 << 10))) {
256
+ if (param.ha) {
257
+ new_descriptor |= 1 << 10; /* AF */
258
+ } else {
259
+ fi->type = ARMFault_AccessFlag;
260
+ goto do_fault;
261
+ }
262
+ }
263
+ }
264
+
265
/*
266
- * Extract attributes from the descriptor, and apply table descriptors.
267
- * Stage 2 table descriptors do not include any attribute fields.
268
- * HPD disables all the table attributes except NSTable.
269
+ * Extract attributes from the (modified) descriptor, and apply
270
+ * table descriptors. Stage 2 table descriptors do not include
271
+ * any attribute fields. HPD disables all the table attributes
272
+ * except NSTable.
273
*/
274
- attrs = descriptor & (MAKE_64BIT_MASK(2, 10) | MAKE_64BIT_MASK(50, 14));
275
+ attrs = new_descriptor & (MAKE_64BIT_MASK(2, 10) | MAKE_64BIT_MASK(50, 14));
276
if (!regime_is_stage2(mmu_idx)) {
277
attrs |= nstable << 5; /* NS */
278
if (!param.hpd) {
279
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
280
}
281
}
282
283
- /*
284
- * Here descaddr is the final physical address, and attributes
285
- * are all in attrs.
286
- */
287
- if ((attrs & (1 << 10)) == 0) {
288
- /* Access flag */
289
- fi->type = ARMFault_AccessFlag;
290
- goto do_fault;
291
- }
292
-
293
ap = extract32(attrs, 6, 2);
294
-
295
if (regime_is_stage2(mmu_idx)) {
296
ns = mmu_idx == ARMMMUIdx_Stage2;
297
xn = extract64(attrs, 53, 2);
298
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
299
goto do_fault;
300
}
301
302
+ /* If FEAT_HAFDBS has made changes, update the PTE. */
303
+ if (new_descriptor != descriptor) {
304
+ new_descriptor = arm_casq_ptw(env, descriptor, new_descriptor, ptw, fi);
305
+ if (fi->type != ARMFault_None) {
306
+ goto do_fault;
307
+ }
308
+ /*
309
+ * I_YZSVV says that if the in-memory descriptor has changed,
310
+ * then we must use the information in that new value
311
+ * (which might include a different output address, different
312
+ * attributes, or generate a fault).
313
+ * Restart the handling of the descriptor value from scratch.
314
+ */
315
+ if (new_descriptor != descriptor) {
316
+ descriptor = new_descriptor;
317
+ goto restart_atomic_update;
318
+ }
319
+ }
320
+
321
if (ns) {
322
/*
323
* The NS bit will (as required by the architecture) have no effect if
324
--
325
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Perform the atomic update for hardware management of the dirty bit.
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20221024051851.3074715-14-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
target/arm/cpu64.c | 2 +-
10
target/arm/ptw.c | 16 ++++++++++++++++
11
2 files changed, 17 insertions(+), 1 deletion(-)
12
13
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu64.c
16
+++ b/target/arm/cpu64.c
17
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
18
cpu->isar.id_aa64mmfr0 = t;
19
20
t = cpu->isar.id_aa64mmfr1;
21
- t = FIELD_DP64(t, ID_AA64MMFR1, HAFDBS, 1); /* FEAT_HAFDBS, AF only */
22
+ t = FIELD_DP64(t, ID_AA64MMFR1, HAFDBS, 2); /* FEAT_HAFDBS */
23
t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* FEAT_VMID16 */
24
t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1); /* FEAT_VHE */
25
t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* FEAT_HPDS */
26
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/ptw.c
29
+++ b/target/arm/ptw.c
30
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
31
goto do_fault;
32
}
33
}
34
+
35
+ /*
36
+ * Dirty Bit.
37
+ * If HD is enabled, pre-emptively set/clear the appropriate AP/S2AP
38
+ * bit for writeback. The actual write protection test may still be
39
+ * overridden by tableattrs, to be merged below.
40
+ */
41
+ if (param.hd
42
+ && extract64(descriptor, 51, 1) /* DBM */
43
+ && access_type == MMU_DATA_STORE) {
44
+ if (regime_is_stage2(mmu_idx)) {
45
+ new_descriptor |= 1ull << 7; /* set S2AP[1] */
46
+ } else {
47
+ new_descriptor &= ~(1ull << 7); /* clear AP[2] */
48
+ }
49
+ }
50
}
51
52
/*
53
--
54
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
We had only been reporting the stage2 page size. This causes
4
problems if stage1 is using a larger page size (16k, 2M, etc),
5
but stage2 is using a smaller page size, because cputlb does
6
not set large_page_{addr,mask} properly.
7
8
Fix by using the max of the two page sizes.
9
10
Reported-by: Marc Zyngier <maz@kernel.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20221024051851.3074715-15-richard.henderson@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
target/arm/ptw.c | 11 ++++++++++-
17
1 file changed, 10 insertions(+), 1 deletion(-)
18
19
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/ptw.c
22
+++ b/target/arm/ptw.c
23
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
24
ARMMMUFaultInfo *fi)
25
{
26
hwaddr ipa;
27
- int s1_prot;
28
+ int s1_prot, s1_lgpgsz;
29
bool is_secure = ptw->in_secure;
30
bool ret, ipa_secure, s2walk_secure;
31
ARMCacheAttrs cacheattrs1;
32
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
33
* Save the stage1 results so that we may merge prot and cacheattrs later.
34
*/
35
s1_prot = result->f.prot;
36
+ s1_lgpgsz = result->f.lg_page_size;
37
cacheattrs1 = result->cacheattrs;
38
memset(result, 0, sizeof(*result));
39
40
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
41
return ret;
42
}
43
44
+ /*
45
+ * Use the maximum of the S1 & S2 page size, so that invalidation
46
+ * of pages > TARGET_PAGE_SIZE works correctly.
47
+ */
48
+ if (result->f.lg_page_size < s1_lgpgsz) {
49
+ result->f.lg_page_size = s1_lgpgsz;
50
+ }
51
+
52
/* Combine the S1 and S2 cache attributes. */
53
hcr = arm_hcr_el2_eff_secstate(env, is_secure);
54
if (hcr & HCR_DC) {
55
--
56
2.25.1
diff view generated by jsdifflib
1
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
2
3
When the system reboots, the rng-seed that the FDT has should be
3
Add a model of Xilinx Versal SoC.
4
re-randomized, so that the new boot gets a new seed. Since the FDT is in
5
the ROM region at this point, we add a hook right after the ROM has been
6
added, so that we have a pointer to that copy of the FDT.
7
4
8
Cc: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Cc: Paul Burton <paulburton@kernel.org>
6
Message-id: 20181102131913.1535-2-edgar.iglesias@xilinx.com
10
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
12
Message-id: 20221025004327.568476-9-Jason@zx2c4.com
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
9
---
16
hw/mips/boston.c | 3 +++
10
hw/arm/Makefile.objs | 1 +
17
1 file changed, 3 insertions(+)
11
include/hw/arm/xlnx-versal.h | 122 +++++++++++
12
hw/arm/xlnx-versal.c | 323 ++++++++++++++++++++++++++++
13
default-configs/aarch64-softmmu.mak | 1 +
14
4 files changed, 447 insertions(+)
15
create mode 100644 include/hw/arm/xlnx-versal.h
16
create mode 100644 hw/arm/xlnx-versal.c
18
17
19
diff --git a/hw/mips/boston.c b/hw/mips/boston.c
18
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
20
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/mips/boston.c
20
--- a/hw/arm/Makefile.objs
22
+++ b/hw/mips/boston.c
21
+++ b/hw/arm/Makefile.objs
22
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
23
obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
24
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
25
obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
26
+obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o
27
obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
28
obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
29
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
30
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
31
new file mode 100644
32
index XXXXXXX..XXXXXXX
33
--- /dev/null
34
+++ b/include/hw/arm/xlnx-versal.h
23
@@ -XXX,XX +XXX,XX @@
35
@@ -XXX,XX +XXX,XX @@
24
#include "sysemu/sysemu.h"
36
+/*
25
#include "sysemu/qtest.h"
37
+ * Model of the Xilinx Versal
26
#include "sysemu/runstate.h"
38
+ *
27
+#include "sysemu/reset.h"
39
+ * Copyright (c) 2018 Xilinx Inc.
28
40
+ * Written by Edgar E. Iglesias
29
#include <libfdt.h>
41
+ *
30
#include "qom/object.h"
42
+ * This program is free software; you can redistribute it and/or modify
31
@@ -XXX,XX +XXX,XX @@ static void boston_mach_init(MachineState *machine)
43
+ * it under the terms of the GNU General Public License version 2 or
32
/* Calculate real fdt size after filter */
44
+ * (at your option) any later version.
33
dt_size = fdt_totalsize(dtb_load_data);
45
+ */
34
rom_add_blob_fixed("dtb", dtb_load_data, dt_size, dtb_paddr);
46
+
35
+ qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
47
+#ifndef XLNX_VERSAL_H
36
+ rom_ptr(dtb_paddr, dt_size));
48
+#define XLNX_VERSAL_H
37
} else {
49
+
38
/* Try to load file as FIT */
50
+#include "hw/sysbus.h"
39
fit_err = load_fit(&boston_fit_loader, machine->kernel_filename, s);
51
+#include "hw/arm/arm.h"
52
+#include "hw/intc/arm_gicv3.h"
53
+
54
+#define TYPE_XLNX_VERSAL "xlnx-versal"
55
+#define XLNX_VERSAL(obj) OBJECT_CHECK(Versal, (obj), TYPE_XLNX_VERSAL)
56
+
57
+#define XLNX_VERSAL_NR_ACPUS 2
58
+#define XLNX_VERSAL_NR_UARTS 2
59
+#define XLNX_VERSAL_NR_GEMS 2
60
+#define XLNX_VERSAL_NR_IRQS 256
61
+
62
+typedef struct Versal {
63
+ /*< private >*/
64
+ SysBusDevice parent_obj;
65
+
66
+ /*< public >*/
67
+ struct {
68
+ struct {
69
+ MemoryRegion mr;
70
+ ARMCPU *cpu[XLNX_VERSAL_NR_ACPUS];
71
+ GICv3State gic;
72
+ } apu;
73
+ } fpd;
74
+
75
+ MemoryRegion mr_ps;
76
+
77
+ struct {
78
+ /* 4 ranges to access DDR. */
79
+ MemoryRegion mr_ddr_ranges[4];
80
+ } noc;
81
+
82
+ struct {
83
+ MemoryRegion mr_ocm;
84
+
85
+ struct {
86
+ SysBusDevice *uart[XLNX_VERSAL_NR_UARTS];
87
+ SysBusDevice *gem[XLNX_VERSAL_NR_GEMS];
88
+ } iou;
89
+ } lpd;
90
+
91
+ struct {
92
+ MemoryRegion *mr_ddr;
93
+ uint32_t psci_conduit;
94
+ } cfg;
95
+} Versal;
96
+
97
+/* Memory-map and IRQ definitions. Copied a subset from
98
+ * auto-generated files. */
99
+
100
+#define VERSAL_GIC_MAINT_IRQ 9
101
+#define VERSAL_TIMER_VIRT_IRQ 11
102
+#define VERSAL_TIMER_S_EL1_IRQ 13
103
+#define VERSAL_TIMER_NS_EL1_IRQ 14
104
+#define VERSAL_TIMER_NS_EL2_IRQ 10
105
+
106
+#define VERSAL_UART0_IRQ_0 18
107
+#define VERSAL_UART1_IRQ_0 19
108
+#define VERSAL_GEM0_IRQ_0 56
109
+#define VERSAL_GEM0_WAKE_IRQ_0 57
110
+#define VERSAL_GEM1_IRQ_0 58
111
+#define VERSAL_GEM1_WAKE_IRQ_0 59
112
+
113
+/* Architecturally eserved IRQs suitable for virtualization. */
114
+#define VERSAL_RSVD_HIGH_IRQ_FIRST 160
115
+#define VERSAL_RSVD_HIGH_IRQ_LAST 255
116
+
117
+#define MM_TOP_RSVD 0xa0000000U
118
+#define MM_TOP_RSVD_SIZE 0x4000000
119
+#define MM_GIC_APU_DIST_MAIN 0xf9000000U
120
+#define MM_GIC_APU_DIST_MAIN_SIZE 0x10000
121
+#define MM_GIC_APU_REDIST_0 0xf9080000U
122
+#define MM_GIC_APU_REDIST_0_SIZE 0x80000
123
+
124
+#define MM_UART0 0xff000000U
125
+#define MM_UART0_SIZE 0x10000
126
+#define MM_UART1 0xff010000U
127
+#define MM_UART1_SIZE 0x10000
128
+
129
+#define MM_GEM0 0xff0c0000U
130
+#define MM_GEM0_SIZE 0x10000
131
+#define MM_GEM1 0xff0d0000U
132
+#define MM_GEM1_SIZE 0x10000
133
+
134
+#define MM_OCM 0xfffc0000U
135
+#define MM_OCM_SIZE 0x40000
136
+
137
+#define MM_TOP_DDR 0x0
138
+#define MM_TOP_DDR_SIZE 0x80000000U
139
+#define MM_TOP_DDR_2 0x800000000ULL
140
+#define MM_TOP_DDR_2_SIZE 0x800000000ULL
141
+#define MM_TOP_DDR_3 0xc000000000ULL
142
+#define MM_TOP_DDR_3_SIZE 0x4000000000ULL
143
+#define MM_TOP_DDR_4 0x10000000000ULL
144
+#define MM_TOP_DDR_4_SIZE 0xb780000000ULL
145
+
146
+#define MM_PSM_START 0xffc80000U
147
+#define MM_PSM_END 0xffcf0000U
148
+
149
+#define MM_CRL 0xff5e0000U
150
+#define MM_CRL_SIZE 0x300000
151
+#define MM_IOU_SCNTR 0xff130000U
152
+#define MM_IOU_SCNTR_SIZE 0x10000
153
+#define MM_IOU_SCNTRS 0xff140000U
154
+#define MM_IOU_SCNTRS_SIZE 0x10000
155
+#define MM_FPD_CRF 0xfd1a0000U
156
+#define MM_FPD_CRF_SIZE 0x140000
157
+#endif
158
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
159
new file mode 100644
160
index XXXXXXX..XXXXXXX
161
--- /dev/null
162
+++ b/hw/arm/xlnx-versal.c
163
@@ -XXX,XX +XXX,XX @@
164
+/*
165
+ * Xilinx Versal SoC model.
166
+ *
167
+ * Copyright (c) 2018 Xilinx Inc.
168
+ * Written by Edgar E. Iglesias
169
+ *
170
+ * This program is free software; you can redistribute it and/or modify
171
+ * it under the terms of the GNU General Public License version 2 or
172
+ * (at your option) any later version.
173
+ */
174
+
175
+#include "qemu/osdep.h"
176
+#include "qapi/error.h"
177
+#include "qemu-common.h"
178
+#include "qemu/log.h"
179
+#include "hw/sysbus.h"
180
+#include "net/net.h"
181
+#include "sysemu/sysemu.h"
182
+#include "sysemu/kvm.h"
183
+#include "hw/arm/arm.h"
184
+#include "kvm_arm.h"
185
+#include "hw/misc/unimp.h"
186
+#include "hw/intc/arm_gicv3_common.h"
187
+#include "hw/arm/xlnx-versal.h"
188
+
189
+#define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
190
+#define GEM_REVISION 0x40070106
191
+
192
+static void versal_create_apu_cpus(Versal *s)
193
+{
194
+ int i;
195
+
196
+ for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) {
197
+ Object *obj;
198
+ char *name;
199
+
200
+ obj = object_new(XLNX_VERSAL_ACPU_TYPE);
201
+ if (!obj) {
202
+ /* Secondary CPUs start in PSCI powered-down state */
203
+ error_report("Unable to create apu.cpu[%d] of type %s",
204
+ i, XLNX_VERSAL_ACPU_TYPE);
205
+ exit(EXIT_FAILURE);
206
+ }
207
+
208
+ name = g_strdup_printf("apu-cpu[%d]", i);
209
+ object_property_add_child(OBJECT(s), name, obj, &error_fatal);
210
+ g_free(name);
211
+
212
+ object_property_set_int(obj, s->cfg.psci_conduit,
213
+ "psci-conduit", &error_abort);
214
+ if (i) {
215
+ object_property_set_bool(obj, true,
216
+ "start-powered-off", &error_abort);
217
+ }
218
+
219
+ object_property_set_int(obj, ARRAY_SIZE(s->fpd.apu.cpu),
220
+ "core-count", &error_abort);
221
+ object_property_set_link(obj, OBJECT(&s->fpd.apu.mr), "memory",
222
+ &error_abort);
223
+ object_property_set_bool(obj, true, "realized", &error_fatal);
224
+ s->fpd.apu.cpu[i] = ARM_CPU(obj);
225
+ }
226
+}
227
+
228
+static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
229
+{
230
+ static const uint64_t addrs[] = {
231
+ MM_GIC_APU_DIST_MAIN,
232
+ MM_GIC_APU_REDIST_0
233
+ };
234
+ SysBusDevice *gicbusdev;
235
+ DeviceState *gicdev;
236
+ int nr_apu_cpus = ARRAY_SIZE(s->fpd.apu.cpu);
237
+ int i;
238
+
239
+ sysbus_init_child_obj(OBJECT(s), "apu-gic",
240
+ &s->fpd.apu.gic, sizeof(s->fpd.apu.gic),
241
+ gicv3_class_name());
242
+ gicbusdev = SYS_BUS_DEVICE(&s->fpd.apu.gic);
243
+ gicdev = DEVICE(&s->fpd.apu.gic);
244
+ qdev_prop_set_uint32(gicdev, "revision", 3);
245
+ qdev_prop_set_uint32(gicdev, "num-cpu", 2);
246
+ qdev_prop_set_uint32(gicdev, "num-irq", XLNX_VERSAL_NR_IRQS + 32);
247
+ qdev_prop_set_uint32(gicdev, "len-redist-region-count", 1);
248
+ qdev_prop_set_uint32(gicdev, "redist-region-count[0]", 2);
249
+ qdev_prop_set_bit(gicdev, "has-security-extensions", true);
250
+
251
+ object_property_set_bool(OBJECT(&s->fpd.apu.gic), true, "realized",
252
+ &error_fatal);
253
+
254
+ for (i = 0; i < ARRAY_SIZE(addrs); i++) {
255
+ MemoryRegion *mr;
256
+
257
+ mr = sysbus_mmio_get_region(gicbusdev, i);
258
+ memory_region_add_subregion(&s->fpd.apu.mr, addrs[i], mr);
259
+ }
260
+
261
+ for (i = 0; i < nr_apu_cpus; i++) {
262
+ DeviceState *cpudev = DEVICE(s->fpd.apu.cpu[i]);
263
+ int ppibase = XLNX_VERSAL_NR_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
264
+ qemu_irq maint_irq;
265
+ int ti;
266
+ /* Mapping from the output timer irq lines from the CPU to the
267
+ * GIC PPI inputs.
268
+ */
269
+ const int timer_irq[] = {
270
+ [GTIMER_PHYS] = VERSAL_TIMER_NS_EL1_IRQ,
271
+ [GTIMER_VIRT] = VERSAL_TIMER_VIRT_IRQ,
272
+ [GTIMER_HYP] = VERSAL_TIMER_NS_EL2_IRQ,
273
+ [GTIMER_SEC] = VERSAL_TIMER_S_EL1_IRQ,
274
+ };
275
+
276
+ for (ti = 0; ti < ARRAY_SIZE(timer_irq); ti++) {
277
+ qdev_connect_gpio_out(cpudev, ti,
278
+ qdev_get_gpio_in(gicdev,
279
+ ppibase + timer_irq[ti]));
280
+ }
281
+ maint_irq = qdev_get_gpio_in(gicdev,
282
+ ppibase + VERSAL_GIC_MAINT_IRQ);
283
+ qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
284
+ 0, maint_irq);
285
+ sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
286
+ sysbus_connect_irq(gicbusdev, i + nr_apu_cpus,
287
+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
288
+ sysbus_connect_irq(gicbusdev, i + 2 * nr_apu_cpus,
289
+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
290
+ sysbus_connect_irq(gicbusdev, i + 3 * nr_apu_cpus,
291
+ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
292
+ }
293
+
294
+ for (i = 0; i < XLNX_VERSAL_NR_IRQS; i++) {
295
+ pic[i] = qdev_get_gpio_in(gicdev, i);
296
+ }
297
+}
298
+
299
+static void versal_create_uarts(Versal *s, qemu_irq *pic)
300
+{
301
+ int i;
302
+
303
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) {
304
+ static const int irqs[] = { VERSAL_UART0_IRQ_0, VERSAL_UART1_IRQ_0};
305
+ static const uint64_t addrs[] = { MM_UART0, MM_UART1 };
306
+ char *name = g_strdup_printf("uart%d", i);
307
+ DeviceState *dev;
308
+ MemoryRegion *mr;
309
+
310
+ dev = qdev_create(NULL, "pl011");
311
+ s->lpd.iou.uart[i] = SYS_BUS_DEVICE(dev);
312
+ qdev_prop_set_chr(dev, "chardev", serial_hd(i));
313
+ object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
314
+ qdev_init_nofail(dev);
315
+
316
+ mr = sysbus_mmio_get_region(s->lpd.iou.uart[i], 0);
317
+ memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
318
+
319
+ sysbus_connect_irq(s->lpd.iou.uart[i], 0, pic[irqs[i]]);
320
+ g_free(name);
321
+ }
322
+}
323
+
324
+static void versal_create_gems(Versal *s, qemu_irq *pic)
325
+{
326
+ int i;
327
+
328
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) {
329
+ static const int irqs[] = { VERSAL_GEM0_IRQ_0, VERSAL_GEM1_IRQ_0};
330
+ static const uint64_t addrs[] = { MM_GEM0, MM_GEM1 };
331
+ char *name = g_strdup_printf("gem%d", i);
332
+ NICInfo *nd = &nd_table[i];
333
+ DeviceState *dev;
334
+ MemoryRegion *mr;
335
+
336
+ dev = qdev_create(NULL, "cadence_gem");
337
+ s->lpd.iou.gem[i] = SYS_BUS_DEVICE(dev);
338
+ object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
339
+ if (nd->used) {
340
+ qemu_check_nic_model(nd, "cadence_gem");
341
+ qdev_set_nic_properties(dev, nd);
342
+ }
343
+ object_property_set_int(OBJECT(s->lpd.iou.gem[i]),
344
+ 2, "num-priority-queues",
345
+ &error_abort);
346
+ object_property_set_link(OBJECT(s->lpd.iou.gem[i]),
347
+ OBJECT(&s->mr_ps), "dma",
348
+ &error_abort);
349
+ qdev_init_nofail(dev);
350
+
351
+ mr = sysbus_mmio_get_region(s->lpd.iou.gem[i], 0);
352
+ memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
353
+
354
+ sysbus_connect_irq(s->lpd.iou.gem[i], 0, pic[irqs[i]]);
355
+ g_free(name);
356
+ }
357
+}
358
+
359
+/* This takes the board allocated linear DDR memory and creates aliases
360
+ * for each split DDR range/aperture on the Versal address map.
361
+ */
362
+static void versal_map_ddr(Versal *s)
363
+{
364
+ uint64_t size = memory_region_size(s->cfg.mr_ddr);
365
+ /* Describes the various split DDR access regions. */
366
+ static const struct {
367
+ uint64_t base;
368
+ uint64_t size;
369
+ } addr_ranges[] = {
370
+ { MM_TOP_DDR, MM_TOP_DDR_SIZE },
371
+ { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE },
372
+ { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE },
373
+ { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE }
374
+ };
375
+ uint64_t offset = 0;
376
+ int i;
377
+
378
+ assert(ARRAY_SIZE(addr_ranges) == ARRAY_SIZE(s->noc.mr_ddr_ranges));
379
+ for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) {
380
+ char *name;
381
+ uint64_t mapsize;
382
+
383
+ mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size;
384
+ name = g_strdup_printf("noc-ddr-range%d", i);
385
+ /* Create the MR alias. */
386
+ memory_region_init_alias(&s->noc.mr_ddr_ranges[i], OBJECT(s),
387
+ name, s->cfg.mr_ddr,
388
+ offset, mapsize);
389
+
390
+ /* Map it onto the NoC MR. */
391
+ memory_region_add_subregion(&s->mr_ps, addr_ranges[i].base,
392
+ &s->noc.mr_ddr_ranges[i]);
393
+ offset += mapsize;
394
+ size -= mapsize;
395
+ g_free(name);
396
+ }
397
+}
398
+
399
+static void versal_unimp_area(Versal *s, const char *name,
400
+ MemoryRegion *mr,
401
+ hwaddr base, hwaddr size)
402
+{
403
+ DeviceState *dev = qdev_create(NULL, TYPE_UNIMPLEMENTED_DEVICE);
404
+ MemoryRegion *mr_dev;
405
+
406
+ qdev_prop_set_string(dev, "name", name);
407
+ qdev_prop_set_uint64(dev, "size", size);
408
+ object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
409
+ qdev_init_nofail(dev);
410
+
411
+ mr_dev = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
412
+ memory_region_add_subregion(mr, base, mr_dev);
413
+}
414
+
415
+static void versal_unimp(Versal *s)
416
+{
417
+ versal_unimp_area(s, "psm", &s->mr_ps,
418
+ MM_PSM_START, MM_PSM_END - MM_PSM_START);
419
+ versal_unimp_area(s, "crl", &s->mr_ps,
420
+ MM_CRL, MM_CRL_SIZE);
421
+ versal_unimp_area(s, "crf", &s->mr_ps,
422
+ MM_FPD_CRF, MM_FPD_CRF_SIZE);
423
+ versal_unimp_area(s, "iou-scntr", &s->mr_ps,
424
+ MM_IOU_SCNTR, MM_IOU_SCNTR_SIZE);
425
+ versal_unimp_area(s, "iou-scntr-seucre", &s->mr_ps,
426
+ MM_IOU_SCNTRS, MM_IOU_SCNTRS_SIZE);
427
+}
428
+
429
+static void versal_realize(DeviceState *dev, Error **errp)
430
+{
431
+ Versal *s = XLNX_VERSAL(dev);
432
+ qemu_irq pic[XLNX_VERSAL_NR_IRQS];
433
+
434
+ versal_create_apu_cpus(s);
435
+ versal_create_apu_gic(s, pic);
436
+ versal_create_uarts(s, pic);
437
+ versal_create_gems(s, pic);
438
+ versal_map_ddr(s);
439
+ versal_unimp(s);
440
+
441
+ /* Create the On Chip Memory (OCM). */
442
+ memory_region_init_ram(&s->lpd.mr_ocm, OBJECT(s), "ocm",
443
+ MM_OCM_SIZE, &error_fatal);
444
+
445
+ memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
446
+ memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
447
+}
448
+
449
+static void versal_init(Object *obj)
450
+{
451
+ Versal *s = XLNX_VERSAL(obj);
452
+
453
+ memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
454
+ memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
455
+}
456
+
457
+static Property versal_properties[] = {
458
+ DEFINE_PROP_LINK("ddr", Versal, cfg.mr_ddr, TYPE_MEMORY_REGION,
459
+ MemoryRegion *),
460
+ DEFINE_PROP_UINT32("psci-conduit", Versal, cfg.psci_conduit, 0),
461
+ DEFINE_PROP_END_OF_LIST()
462
+};
463
+
464
+static void versal_class_init(ObjectClass *klass, void *data)
465
+{
466
+ DeviceClass *dc = DEVICE_CLASS(klass);
467
+
468
+ dc->realize = versal_realize;
469
+ dc->props = versal_properties;
470
+ /* No VMSD since we haven't got any top-level SoC state to save. */
471
+}
472
+
473
+static const TypeInfo versal_info = {
474
+ .name = TYPE_XLNX_VERSAL,
475
+ .parent = TYPE_SYS_BUS_DEVICE,
476
+ .instance_size = sizeof(Versal),
477
+ .instance_init = versal_init,
478
+ .class_init = versal_class_init,
479
+};
480
+
481
+static void versal_register_types(void)
482
+{
483
+ type_register_static(&versal_info);
484
+}
485
+
486
+type_init(versal_register_types);
487
diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak
488
index XXXXXXX..XXXXXXX 100644
489
--- a/default-configs/aarch64-softmmu.mak
490
+++ b/default-configs/aarch64-softmmu.mak
491
@@ -XXX,XX +XXX,XX @@ CONFIG_DDC=y
492
CONFIG_DPCD=y
493
CONFIG_XLNX_ZYNQMP=y
494
CONFIG_XLNX_ZYNQMP_ARM=y
495
+CONFIG_XLNX_VERSAL=y
496
CONFIG_ARM_SMMUV3=y
40
--
497
--
41
2.25.1
498
2.19.1
42
499
43
500
diff view generated by jsdifflib
1
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
2
3
Snapshot loading only expects to call deterministic handlers, not
3
Add a virtual Xilinx Versal board.
4
non-deterministic ones. So introduce a way of registering handlers that
5
won't be called when reseting for snapshots.
6
4
7
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
5
This board is based on the Xilinx Versal SoC. The exact
8
Message-id: 20221025004327.568476-2-Jason@zx2c4.com
6
details of what peripherals are attached to this board
9
[PMM: updated json doc comment with Markus' text; fixed
7
will remain in control of QEMU. QEMU will generate an
10
checkpatch style nit]
8
FDT on the fly for Linux and other software to auto-discover
9
peripherals.
10
11
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
12
Message-id: 20181102131913.1535-3-edgar.iglesias@xilinx.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
15
---
14
qapi/run-state.json | 6 +++++-
16
hw/arm/Makefile.objs | 2 +-
15
include/hw/boards.h | 2 +-
17
hw/arm/xlnx-versal-virt.c | 494 ++++++++++++++++++++++++++++++++++++++
16
include/sysemu/reset.h | 5 ++++-
18
2 files changed, 495 insertions(+), 1 deletion(-)
17
hw/arm/aspeed.c | 4 ++--
19
create mode 100644 hw/arm/xlnx-versal-virt.c
18
hw/arm/mps2-tz.c | 4 ++--
19
hw/core/reset.c | 17 ++++++++++++++++-
20
hw/hppa/machine.c | 4 ++--
21
hw/i386/microvm.c | 4 ++--
22
hw/i386/pc.c | 6 +++---
23
hw/ppc/pegasos2.c | 4 ++--
24
hw/ppc/pnv.c | 4 ++--
25
hw/ppc/spapr.c | 4 ++--
26
hw/s390x/s390-virtio-ccw.c | 4 ++--
27
migration/savevm.c | 2 +-
28
softmmu/runstate.c | 11 ++++++++---
29
15 files changed, 54 insertions(+), 27 deletions(-)
30
20
31
diff --git a/qapi/run-state.json b/qapi/run-state.json
21
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
32
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
33
--- a/qapi/run-state.json
23
--- a/hw/arm/Makefile.objs
34
+++ b/qapi/run-state.json
24
+++ b/hw/arm/Makefile.objs
25
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
26
obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
27
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
28
obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
29
-obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o
30
+obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
31
obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
32
obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
33
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
34
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
35
new file mode 100644
36
index XXXXXXX..XXXXXXX
37
--- /dev/null
38
+++ b/hw/arm/xlnx-versal-virt.c
35
@@ -XXX,XX +XXX,XX @@
39
@@ -XXX,XX +XXX,XX @@
36
# ignores --no-reboot. This is useful for sanitizing
40
+/*
37
# hypercalls on s390 that are used during kexec/kdump/boot
41
+ * Xilinx Versal Virtual board.
38
#
42
+ *
39
+# @snapshot-load: A snapshot is being loaded by the record & replay
43
+ * Copyright (c) 2018 Xilinx Inc.
40
+# subsystem. This value is used only within QEMU. It
44
+ * Written by Edgar E. Iglesias
41
+# doesn't occur in QMP. (since 7.2)
45
+ *
42
+#
46
+ * This program is free software; you can redistribute it and/or modify
43
##
47
+ * it under the terms of the GNU General Public License version 2 or
44
{ 'enum': 'ShutdownCause',
48
+ * (at your option) any later version.
45
# Beware, shutdown_caused_by_guest() depends on enumeration order
49
+ */
46
'data': [ 'none', 'host-error', 'host-qmp-quit', 'host-qmp-system-reset',
50
+
47
'host-signal', 'host-ui', 'guest-shutdown', 'guest-reset',
51
+#include "qemu/osdep.h"
48
- 'guest-panic', 'subsystem-reset'] }
52
+#include "qemu/log.h"
49
+ 'guest-panic', 'subsystem-reset', 'snapshot-load'] }
53
+#include "qemu/error-report.h"
50
54
+#include "qapi/error.h"
51
##
55
+#include "sysemu/device_tree.h"
52
# @StatusInfo:
56
+#include "exec/address-spaces.h"
53
diff --git a/include/hw/boards.h b/include/hw/boards.h
57
+#include "hw/boards.h"
54
index XXXXXXX..XXXXXXX 100644
58
+#include "hw/sysbus.h"
55
--- a/include/hw/boards.h
59
+#include "hw/arm/sysbus-fdt.h"
56
+++ b/include/hw/boards.h
60
+#include "hw/arm/fdt.h"
57
@@ -XXX,XX +XXX,XX @@ struct MachineClass {
61
+#include "cpu.h"
58
const char *deprecation_reason;
62
+#include "hw/arm/xlnx-versal.h"
59
63
+
60
void (*init)(MachineState *state);
64
+#define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("xlnx-versal-virt")
61
- void (*reset)(MachineState *state);
65
+#define XLNX_VERSAL_VIRT_MACHINE(obj) \
62
+ void (*reset)(MachineState *state, ShutdownCause reason);
66
+ OBJECT_CHECK(VersalVirt, (obj), TYPE_XLNX_VERSAL_VIRT_MACHINE)
63
void (*wakeup)(MachineState *state);
67
+
64
int (*kvm_type)(MachineState *machine, const char *arg);
68
+typedef struct VersalVirt {
65
69
+ MachineState parent_obj;
66
diff --git a/include/sysemu/reset.h b/include/sysemu/reset.h
70
+
67
index XXXXXXX..XXXXXXX 100644
71
+ Versal soc;
68
--- a/include/sysemu/reset.h
72
+ MemoryRegion mr_ddr;
69
+++ b/include/sysemu/reset.h
73
+
70
@@ -XXX,XX +XXX,XX @@
74
+ void *fdt;
71
#ifndef QEMU_SYSEMU_RESET_H
75
+ int fdt_size;
72
#define QEMU_SYSEMU_RESET_H
76
+ struct {
73
77
+ uint32_t gic;
74
+#include "qapi/qapi-events-run-state.h"
78
+ uint32_t ethernet_phy[2];
75
+
79
+ uint32_t clk_125Mhz;
76
typedef void QEMUResetHandler(void *opaque);
80
+ uint32_t clk_25Mhz;
77
81
+ } phandle;
78
void qemu_register_reset(QEMUResetHandler *func, void *opaque);
82
+ struct arm_boot_info binfo;
79
+void qemu_register_reset_nosnapshotload(QEMUResetHandler *func, void *opaque);
83
+
80
void qemu_unregister_reset(QEMUResetHandler *func, void *opaque);
84
+ struct {
81
-void qemu_devices_reset(void);
85
+ bool secure;
82
+void qemu_devices_reset(ShutdownCause reason);
86
+ } cfg;
83
87
+} VersalVirt;
84
#endif
88
+
85
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
89
+static void fdt_create(VersalVirt *s)
86
index XXXXXXX..XXXXXXX 100644
90
+{
87
--- a/hw/arm/aspeed.c
91
+ MachineClass *mc = MACHINE_GET_CLASS(s);
88
+++ b/hw/arm/aspeed.c
92
+ int i;
89
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_bletchley_class_init(ObjectClass *oc, void *data)
93
+
90
aspeed_soc_num_cpus(amc->soc_name);
94
+ s->fdt = create_device_tree(&s->fdt_size);
91
}
95
+ if (!s->fdt) {
92
96
+ error_report("create_device_tree() failed");
93
-static void fby35_reset(MachineState *state)
97
+ exit(1);
94
+static void fby35_reset(MachineState *state, ShutdownCause reason)
98
+ }
95
{
99
+
96
AspeedMachineState *bmc = ASPEED_MACHINE(state);
100
+ /* Allocate all phandles. */
97
AspeedGPIOState *gpio = &bmc->soc.gpio;
101
+ s->phandle.gic = qemu_fdt_alloc_phandle(s->fdt);
98
102
+ for (i = 0; i < ARRAY_SIZE(s->phandle.ethernet_phy); i++) {
99
- qemu_devices_reset();
103
+ s->phandle.ethernet_phy[i] = qemu_fdt_alloc_phandle(s->fdt);
100
+ qemu_devices_reset(reason);
104
+ }
101
105
+ s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);
102
/* Board ID: 7 (Class-1, 4 slots) */
106
+ s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);
103
object_property_set_bool(OBJECT(gpio), "gpioV4", true, &error_fatal);
107
+
104
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
108
+ /* Create /chosen node for load_dtb. */
105
index XXXXXXX..XXXXXXX 100644
109
+ qemu_fdt_add_subnode(s->fdt, "/chosen");
106
--- a/hw/arm/mps2-tz.c
110
+
107
+++ b/hw/arm/mps2-tz.c
111
+ /* Header */
108
@@ -XXX,XX +XXX,XX @@ static void mps2_set_remap(Object *obj, const char *value, Error **errp)
112
+ qemu_fdt_setprop_cell(s->fdt, "/", "interrupt-parent", s->phandle.gic);
109
}
113
+ qemu_fdt_setprop_cell(s->fdt, "/", "#size-cells", 0x2);
110
}
114
+ qemu_fdt_setprop_cell(s->fdt, "/", "#address-cells", 0x2);
111
115
+ qemu_fdt_setprop_string(s->fdt, "/", "model", mc->desc);
112
-static void mps2_machine_reset(MachineState *machine)
116
+ qemu_fdt_setprop_string(s->fdt, "/", "compatible", "xlnx-versal-virt");
113
+static void mps2_machine_reset(MachineState *machine, ShutdownCause reason)
117
+}
114
{
118
+
115
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
119
+static void fdt_add_clk_node(VersalVirt *s, const char *name,
116
120
+ unsigned int freq_hz, uint32_t phandle)
117
@@ -XXX,XX +XXX,XX @@ static void mps2_machine_reset(MachineState *machine)
121
+{
118
* reset see the correct mapping.
122
+ qemu_fdt_add_subnode(s->fdt, name);
119
*/
123
+ qemu_fdt_setprop_cell(s->fdt, name, "phandle", phandle);
120
remap_memory(mms, mms->remap);
124
+ qemu_fdt_setprop_cell(s->fdt, name, "clock-frequency", freq_hz);
121
- qemu_devices_reset();
125
+ qemu_fdt_setprop_cell(s->fdt, name, "#clock-cells", 0x0);
122
+ qemu_devices_reset(reason);
126
+ qemu_fdt_setprop_string(s->fdt, name, "compatible", "fixed-clock");
123
}
127
+ qemu_fdt_setprop(s->fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
124
128
+}
125
static void mps2tz_class_init(ObjectClass *oc, void *data)
129
+
126
diff --git a/hw/core/reset.c b/hw/core/reset.c
130
+static void fdt_add_cpu_nodes(VersalVirt *s, uint32_t psci_conduit)
127
index XXXXXXX..XXXXXXX 100644
131
+{
128
--- a/hw/core/reset.c
132
+ int i;
129
+++ b/hw/core/reset.c
133
+
130
@@ -XXX,XX +XXX,XX @@ typedef struct QEMUResetEntry {
134
+ qemu_fdt_add_subnode(s->fdt, "/cpus");
131
QTAILQ_ENTRY(QEMUResetEntry) entry;
135
+ qemu_fdt_setprop_cell(s->fdt, "/cpus", "#size-cells", 0x0);
132
QEMUResetHandler *func;
136
+ qemu_fdt_setprop_cell(s->fdt, "/cpus", "#address-cells", 1);
133
void *opaque;
137
+
134
+ bool skip_on_snapshot_load;
138
+ for (i = XLNX_VERSAL_NR_ACPUS - 1; i >= 0; i--) {
135
} QEMUResetEntry;
139
+ char *name = g_strdup_printf("/cpus/cpu@%d", i);
136
140
+ ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i));
137
static QTAILQ_HEAD(, QEMUResetEntry) reset_handlers =
141
+
138
@@ -XXX,XX +XXX,XX @@ void qemu_register_reset(QEMUResetHandler *func, void *opaque)
142
+ qemu_fdt_add_subnode(s->fdt, name);
139
QTAILQ_INSERT_TAIL(&reset_handlers, re, entry);
143
+ qemu_fdt_setprop_cell(s->fdt, name, "reg", armcpu->mp_affinity);
140
}
144
+ if (psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
141
145
+ qemu_fdt_setprop_string(s->fdt, name, "enable-method", "psci");
142
+void qemu_register_reset_nosnapshotload(QEMUResetHandler *func, void *opaque)
143
+{
144
+ QEMUResetEntry *re = g_new0(QEMUResetEntry, 1);
145
+
146
+ re->func = func;
147
+ re->opaque = opaque;
148
+ re->skip_on_snapshot_load = true;
149
+ QTAILQ_INSERT_TAIL(&reset_handlers, re, entry);
150
+}
151
+
152
void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
153
{
154
QEMUResetEntry *re;
155
@@ -XXX,XX +XXX,XX @@ void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
156
}
157
}
158
159
-void qemu_devices_reset(void)
160
+void qemu_devices_reset(ShutdownCause reason)
161
{
162
QEMUResetEntry *re, *nre;
163
164
/* reset all devices */
165
QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
166
+ if (reason == SHUTDOWN_CAUSE_SNAPSHOT_LOAD &&
167
+ re->skip_on_snapshot_load) {
168
+ continue;
169
+ }
146
+ }
170
re->func(re->opaque);
147
+ qemu_fdt_setprop_string(s->fdt, name, "device_type", "cpu");
171
}
148
+ qemu_fdt_setprop_string(s->fdt, name, "compatible",
172
}
149
+ armcpu->dtb_compatible);
173
diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
150
+ g_free(name);
174
index XXXXXXX..XXXXXXX 100644
151
+ }
175
--- a/hw/hppa/machine.c
152
+}
176
+++ b/hw/hppa/machine.c
153
+
177
@@ -XXX,XX +XXX,XX @@ static void machine_hppa_init(MachineState *machine)
154
+static void fdt_add_gic_nodes(VersalVirt *s)
178
cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
155
+{
179
}
156
+ char *nodename;
180
157
+
181
-static void hppa_machine_reset(MachineState *ms)
158
+ nodename = g_strdup_printf("/gic@%x", MM_GIC_APU_DIST_MAIN);
182
+static void hppa_machine_reset(MachineState *ms, ShutdownCause reason)
159
+ qemu_fdt_add_subnode(s->fdt, nodename);
183
{
160
+ qemu_fdt_setprop_cell(s->fdt, nodename, "phandle", s->phandle.gic);
184
unsigned int smp_cpus = ms->smp.cpus;
161
+ qemu_fdt_setprop_cells(s->fdt, nodename, "interrupts",
185
int i;
162
+ GIC_FDT_IRQ_TYPE_PPI, VERSAL_GIC_MAINT_IRQ,
186
163
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI);
187
- qemu_devices_reset();
164
+ qemu_fdt_setprop(s->fdt, nodename, "interrupt-controller", NULL, 0);
188
+ qemu_devices_reset(reason);
165
+ qemu_fdt_setprop_sized_cells(s->fdt, nodename, "reg",
189
166
+ 2, MM_GIC_APU_DIST_MAIN,
190
/* Start all CPUs at the firmware entry point.
167
+ 2, MM_GIC_APU_DIST_MAIN_SIZE,
191
* Monarch CPU will initialize firmware, secondary CPUs
168
+ 2, MM_GIC_APU_REDIST_0,
192
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
169
+ 2, MM_GIC_APU_REDIST_0_SIZE);
193
index XXXXXXX..XXXXXXX 100644
170
+ qemu_fdt_setprop_cell(s->fdt, nodename, "#interrupt-cells", 3);
194
--- a/hw/i386/microvm.c
171
+ qemu_fdt_setprop_string(s->fdt, nodename, "compatible", "arm,gic-v3");
195
+++ b/hw/i386/microvm.c
172
+}
196
@@ -XXX,XX +XXX,XX @@ static void microvm_machine_state_init(MachineState *machine)
173
+
197
microvm_devices_init(mms);
174
+static void fdt_add_timer_nodes(VersalVirt *s)
198
}
175
+{
199
176
+ const char compat[] = "arm,armv8-timer";
200
-static void microvm_machine_reset(MachineState *machine)
177
+ uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
201
+static void microvm_machine_reset(MachineState *machine, ShutdownCause reason)
178
+
202
{
179
+ qemu_fdt_add_subnode(s->fdt, "/timer");
203
MicrovmMachineState *mms = MICROVM_MACHINE(machine);
180
+ qemu_fdt_setprop_cells(s->fdt, "/timer", "interrupts",
204
CPUState *cs;
181
+ GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_S_EL1_IRQ, irqflags,
205
@@ -XXX,XX +XXX,XX @@ static void microvm_machine_reset(MachineState *machine)
182
+ GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL1_IRQ, irqflags,
206
mms->kernel_cmdline_fixed = true;
183
+ GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_VIRT_IRQ, irqflags,
207
}
184
+ GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL2_IRQ, irqflags);
208
185
+ qemu_fdt_setprop(s->fdt, "/timer", "compatible",
209
- qemu_devices_reset();
186
+ compat, sizeof(compat));
210
+ qemu_devices_reset(reason);
187
+}
211
188
+
212
CPU_FOREACH(cs) {
189
+static void fdt_add_uart_nodes(VersalVirt *s)
213
cpu = X86_CPU(cs);
190
+{
214
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
191
+ uint64_t addrs[] = { MM_UART1, MM_UART0 };
215
index XXXXXXX..XXXXXXX 100644
192
+ unsigned int irqs[] = { VERSAL_UART1_IRQ_0, VERSAL_UART0_IRQ_0 };
216
--- a/hw/i386/pc.c
193
+ const char compat[] = "arm,pl011\0arm,sbsa-uart";
217
+++ b/hw/i386/pc.c
194
+ const char clocknames[] = "uartclk\0apb_pclk";
218
@@ -XXX,XX +XXX,XX @@ static void pc_machine_initfn(Object *obj)
195
+ int i;
219
cxl_machine_init(obj, &pcms->cxl_devices_state);
196
+
220
}
197
+ for (i = 0; i < ARRAY_SIZE(addrs); i++) {
221
198
+ char *name = g_strdup_printf("/uart@%" PRIx64, addrs[i]);
222
-static void pc_machine_reset(MachineState *machine)
199
+ qemu_fdt_add_subnode(s->fdt, name);
223
+static void pc_machine_reset(MachineState *machine, ShutdownCause reason)
200
+ qemu_fdt_setprop_cell(s->fdt, name, "current-speed", 115200);
224
{
201
+ qemu_fdt_setprop_cells(s->fdt, name, "clocks",
225
CPUState *cs;
202
+ s->phandle.clk_125Mhz, s->phandle.clk_125Mhz);
226
X86CPU *cpu;
203
+ qemu_fdt_setprop(s->fdt, name, "clock-names",
227
204
+ clocknames, sizeof(clocknames));
228
- qemu_devices_reset();
205
+
229
+ qemu_devices_reset(reason);
206
+ qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
230
207
+ GIC_FDT_IRQ_TYPE_SPI, irqs[i],
231
/* Reset APIC after devices have been reset to cancel
208
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI);
232
* any changes that qemu_devices_reset() might have done.
209
+ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
233
@@ -XXX,XX +XXX,XX @@ static void pc_machine_reset(MachineState *machine)
210
+ 2, addrs[i], 2, 0x1000);
234
static void pc_machine_wakeup(MachineState *machine)
211
+ qemu_fdt_setprop(s->fdt, name, "compatible",
235
{
212
+ compat, sizeof(compat));
236
cpu_synchronize_all_states();
213
+ qemu_fdt_setprop(s->fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
237
- pc_machine_reset(machine);
214
+
238
+ pc_machine_reset(machine, SHUTDOWN_CAUSE_NONE);
215
+ if (addrs[i] == MM_UART0) {
239
cpu_synchronize_all_post_reset();
216
+ /* Select UART0. */
240
}
217
+ qemu_fdt_setprop_string(s->fdt, "/chosen", "stdout-path", name);
241
218
+ }
242
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
219
+ g_free(name);
243
index XXXXXXX..XXXXXXX 100644
220
+ }
244
--- a/hw/ppc/pegasos2.c
221
+}
245
+++ b/hw/ppc/pegasos2.c
222
+
246
@@ -XXX,XX +XXX,XX @@ static void pegasos2_pci_config_write(Pegasos2MachineState *pm, int bus,
223
+static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname,
247
pegasos2_mv_reg_write(pm, pcicfg + 4, len, val);
224
+ uint32_t phandle)
248
}
225
+{
249
226
+ char *name = g_strdup_printf("%s/fixed-link", gemname);
250
-static void pegasos2_machine_reset(MachineState *machine)
227
+
251
+static void pegasos2_machine_reset(MachineState *machine, ShutdownCause reason)
228
+ qemu_fdt_add_subnode(s->fdt, name);
252
{
229
+ qemu_fdt_setprop_cell(s->fdt, name, "phandle", phandle);
253
Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
230
+ qemu_fdt_setprop(s->fdt, name, "full-duplex", NULL, 0);
254
void *fdt;
231
+ qemu_fdt_setprop_cell(s->fdt, name, "speed", 1000);
255
uint64_t d[2];
232
+ g_free(name);
256
int sz;
233
+}
257
234
+
258
- qemu_devices_reset();
235
+static void fdt_add_gem_nodes(VersalVirt *s)
259
+ qemu_devices_reset(reason);
236
+{
260
if (!pm->vof) {
237
+ uint64_t addrs[] = { MM_GEM1, MM_GEM0 };
261
return; /* Firmware should set up machine so nothing to do */
238
+ unsigned int irqs[] = { VERSAL_GEM1_IRQ_0, VERSAL_GEM0_IRQ_0 };
262
}
239
+ const char clocknames[] = "pclk\0hclk\0tx_clk\0rx_clk";
263
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
240
+ const char compat_gem[] = "cdns,zynqmp-gem\0cdns,gem";
264
index XXXXXXX..XXXXXXX 100644
241
+ int i;
265
--- a/hw/ppc/pnv.c
242
+
266
+++ b/hw/ppc/pnv.c
243
+ for (i = 0; i < ARRAY_SIZE(addrs); i++) {
267
@@ -XXX,XX +XXX,XX @@ static void pnv_powerdown_notify(Notifier *n, void *opaque)
244
+ char *name = g_strdup_printf("/ethernet@%" PRIx64, addrs[i]);
268
}
245
+ qemu_fdt_add_subnode(s->fdt, name);
269
}
246
+
270
247
+ fdt_add_fixed_link_nodes(s, name, s->phandle.ethernet_phy[i]);
271
-static void pnv_reset(MachineState *machine)
248
+ qemu_fdt_setprop_string(s->fdt, name, "phy-mode", "rgmii-id");
272
+static void pnv_reset(MachineState *machine, ShutdownCause reason)
249
+ qemu_fdt_setprop_cell(s->fdt, name, "phy-handle",
273
{
250
+ s->phandle.ethernet_phy[i]);
274
PnvMachineState *pnv = PNV_MACHINE(machine);
251
+ qemu_fdt_setprop_cells(s->fdt, name, "clocks",
275
IPMIBmc *bmc;
252
+ s->phandle.clk_25Mhz, s->phandle.clk_25Mhz,
276
void *fdt;
253
+ s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
277
254
+ qemu_fdt_setprop(s->fdt, name, "clock-names",
278
- qemu_devices_reset();
255
+ clocknames, sizeof(clocknames));
279
+ qemu_devices_reset(reason);
256
+ qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
280
257
+ GIC_FDT_IRQ_TYPE_SPI, irqs[i],
281
/*
258
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI,
282
* The machine should provide by default an internal BMC simulator.
259
+ GIC_FDT_IRQ_TYPE_SPI, irqs[i],
283
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
260
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI);
284
index XXXXXXX..XXXXXXX 100644
261
+ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
285
--- a/hw/ppc/spapr.c
262
+ 2, addrs[i], 2, 0x1000);
286
+++ b/hw/ppc/spapr.c
263
+ qemu_fdt_setprop(s->fdt, name, "compatible",
287
@@ -XXX,XX +XXX,XX @@ void spapr_check_mmu_mode(bool guest_radix)
264
+ compat_gem, sizeof(compat_gem));
288
}
265
+ qemu_fdt_setprop_cell(s->fdt, name, "#address-cells", 1);
289
}
266
+ qemu_fdt_setprop_cell(s->fdt, name, "#size-cells", 0);
290
267
+ g_free(name);
291
-static void spapr_machine_reset(MachineState *machine)
268
+ }
292
+static void spapr_machine_reset(MachineState *machine, ShutdownCause reason)
269
+}
293
{
270
+
294
SpaprMachineState *spapr = SPAPR_MACHINE(machine);
271
+static void fdt_nop_memory_nodes(void *fdt, Error **errp)
295
PowerPCCPU *first_ppc_cpu;
272
+{
296
@@ -XXX,XX +XXX,XX @@ static void spapr_machine_reset(MachineState *machine)
273
+ Error *err = NULL;
297
spapr_setup_hpt(spapr);
274
+ char **node_path;
298
}
275
+ int n = 0;
299
276
+
300
- qemu_devices_reset();
277
+ node_path = qemu_fdt_node_unit_path(fdt, "memory", &err);
301
+ qemu_devices_reset(reason);
278
+ if (err) {
302
279
+ error_propagate(errp, err);
303
spapr_ovec_cleanup(spapr->ov5_cas);
280
+ return;
304
spapr->ov5_cas = spapr_ovec_new();
281
+ }
305
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
282
+ while (node_path[n]) {
306
index XXXXXXX..XXXXXXX 100644
283
+ if (g_str_has_prefix(node_path[n], "/memory")) {
307
--- a/hw/s390x/s390-virtio-ccw.c
284
+ qemu_fdt_nop_node(fdt, node_path[n]);
308
+++ b/hw/s390x/s390-virtio-ccw.c
285
+ }
309
@@ -XXX,XX +XXX,XX @@ static void s390_pv_prepare_reset(S390CcwMachineState *ms)
286
+ n++;
310
s390_pv_prep_reset();
287
+ }
311
}
288
+ g_strfreev(node_path);
312
289
+}
313
-static void s390_machine_reset(MachineState *machine)
290
+
314
+static void s390_machine_reset(MachineState *machine, ShutdownCause reason)
291
+static void fdt_add_memory_nodes(VersalVirt *s, void *fdt, uint64_t ram_size)
315
{
292
+{
316
S390CcwMachineState *ms = S390_CCW_MACHINE(machine);
293
+ /* Describes the various split DDR access regions. */
317
enum s390_reset reset_type;
294
+ static const struct {
318
@@ -XXX,XX +XXX,XX @@ static void s390_machine_reset(MachineState *machine)
295
+ uint64_t base;
319
s390_machine_unprotect(ms);
296
+ uint64_t size;
320
}
297
+ } addr_ranges[] = {
321
298
+ { MM_TOP_DDR, MM_TOP_DDR_SIZE },
322
- qemu_devices_reset();
299
+ { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE },
323
+ qemu_devices_reset(reason);
300
+ { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE },
324
s390_crypto_reset();
301
+ { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE }
325
302
+ };
326
/* configure and start the ipl CPU only */
303
+ uint64_t mem_reg_prop[8] = {0};
327
diff --git a/migration/savevm.c b/migration/savevm.c
304
+ uint64_t size = ram_size;
328
index XXXXXXX..XXXXXXX 100644
305
+ Error *err = NULL;
329
--- a/migration/savevm.c
306
+ char *name;
330
+++ b/migration/savevm.c
307
+ int i;
331
@@ -XXX,XX +XXX,XX @@ bool load_snapshot(const char *name, const char *vmstate,
308
+
332
goto err_drain;
309
+ fdt_nop_memory_nodes(fdt, &err);
333
}
310
+ if (err) {
334
311
+ error_report_err(err);
335
- qemu_system_reset(SHUTDOWN_CAUSE_NONE);
312
+ return;
336
+ qemu_system_reset(SHUTDOWN_CAUSE_SNAPSHOT_LOAD);
313
+ }
337
mis->from_src_file = f;
314
+
338
315
+ name = g_strdup_printf("/memory@%x", MM_TOP_DDR);
339
if (!yank_register_instance(MIGRATION_YANK_INSTANCE, errp)) {
316
+ for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) {
340
diff --git a/softmmu/runstate.c b/softmmu/runstate.c
317
+ uint64_t mapsize;
341
index XXXXXXX..XXXXXXX 100644
318
+
342
--- a/softmmu/runstate.c
319
+ mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size;
343
+++ b/softmmu/runstate.c
320
+
344
@@ -XXX,XX +XXX,XX @@ void qemu_system_reset(ShutdownCause reason)
321
+ mem_reg_prop[i * 2] = addr_ranges[i].base;
345
cpu_synchronize_all_states();
322
+ mem_reg_prop[i * 2 + 1] = mapsize;
346
323
+ size -= mapsize;
347
if (mc && mc->reset) {
324
+ }
348
- mc->reset(current_machine);
325
+ qemu_fdt_add_subnode(fdt, name);
349
+ mc->reset(current_machine, reason);
326
+ qemu_fdt_setprop_string(fdt, name, "device_type", "memory");
350
} else {
327
+
351
- qemu_devices_reset();
328
+ switch (i) {
352
+ qemu_devices_reset(reason);
329
+ case 1:
353
}
330
+ qemu_fdt_setprop_sized_cells(fdt, name, "reg",
354
- if (reason && reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) {
331
+ 2, mem_reg_prop[0],
355
+ switch (reason) {
332
+ 2, mem_reg_prop[1]);
356
+ case SHUTDOWN_CAUSE_NONE:
333
+ break;
357
+ case SHUTDOWN_CAUSE_SUBSYSTEM_RESET:
334
+ case 2:
358
+ case SHUTDOWN_CAUSE_SNAPSHOT_LOAD:
335
+ qemu_fdt_setprop_sized_cells(fdt, name, "reg",
336
+ 2, mem_reg_prop[0],
337
+ 2, mem_reg_prop[1],
338
+ 2, mem_reg_prop[2],
339
+ 2, mem_reg_prop[3]);
340
+ break;
341
+ case 3:
342
+ qemu_fdt_setprop_sized_cells(fdt, name, "reg",
343
+ 2, mem_reg_prop[0],
344
+ 2, mem_reg_prop[1],
345
+ 2, mem_reg_prop[2],
346
+ 2, mem_reg_prop[3],
347
+ 2, mem_reg_prop[4],
348
+ 2, mem_reg_prop[5]);
349
+ break;
350
+ case 4:
351
+ qemu_fdt_setprop_sized_cells(fdt, name, "reg",
352
+ 2, mem_reg_prop[0],
353
+ 2, mem_reg_prop[1],
354
+ 2, mem_reg_prop[2],
355
+ 2, mem_reg_prop[3],
356
+ 2, mem_reg_prop[4],
357
+ 2, mem_reg_prop[5],
358
+ 2, mem_reg_prop[6],
359
+ 2, mem_reg_prop[7]);
359
+ break;
360
+ break;
360
+ default:
361
+ default:
361
qapi_event_send_reset(shutdown_caused_by_guest(reason), reason);
362
+ g_assert_not_reached();
362
}
363
+ }
363
cpu_synchronize_all_post_reset();
364
+ g_free(name);
365
+}
366
+
367
+static void versal_virt_modify_dtb(const struct arm_boot_info *binfo,
368
+ void *fdt)
369
+{
370
+ VersalVirt *s = container_of(binfo, VersalVirt, binfo);
371
+
372
+ fdt_add_memory_nodes(s, fdt, binfo->ram_size);
373
+}
374
+
375
+static void *versal_virt_get_dtb(const struct arm_boot_info *binfo,
376
+ int *fdt_size)
377
+{
378
+ const VersalVirt *board = container_of(binfo, VersalVirt, binfo);
379
+
380
+ *fdt_size = board->fdt_size;
381
+ return board->fdt;
382
+}
383
+
384
+#define NUM_VIRTIO_TRANSPORT 32
385
+static void create_virtio_regions(VersalVirt *s)
386
+{
387
+ int virtio_mmio_size = 0x200;
388
+ int i;
389
+
390
+ for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) {
391
+ char *name = g_strdup_printf("virtio%d", i);;
392
+ hwaddr base = MM_TOP_RSVD + i * virtio_mmio_size;
393
+ int irq = VERSAL_RSVD_HIGH_IRQ_FIRST + i;
394
+ MemoryRegion *mr;
395
+ DeviceState *dev;
396
+ qemu_irq pic_irq;
397
+
398
+ pic_irq = qdev_get_gpio_in(DEVICE(&s->soc.fpd.apu.gic), irq);
399
+ dev = qdev_create(NULL, "virtio-mmio");
400
+ object_property_add_child(OBJECT(&s->soc), name, OBJECT(dev),
401
+ &error_fatal);
402
+ qdev_init_nofail(dev);
403
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic_irq);
404
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
405
+ memory_region_add_subregion(&s->soc.mr_ps, base, mr);
406
+ sysbus_create_simple("virtio-mmio", base, pic_irq);
407
+ }
408
+
409
+ for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) {
410
+ hwaddr base = MM_TOP_RSVD + i * virtio_mmio_size;
411
+ int irq = VERSAL_RSVD_HIGH_IRQ_FIRST + i;
412
+ char *name = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
413
+
414
+ qemu_fdt_add_subnode(s->fdt, name);
415
+ qemu_fdt_setprop(s->fdt, name, "dma-coherent", NULL, 0);
416
+ qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
417
+ GIC_FDT_IRQ_TYPE_SPI, irq,
418
+ GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
419
+ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
420
+ 2, base, 2, virtio_mmio_size);
421
+ qemu_fdt_setprop_string(s->fdt, name, "compatible", "virtio,mmio");
422
+ g_free(name);
423
+ }
424
+}
425
+
426
+static void versal_virt_init(MachineState *machine)
427
+{
428
+ VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(machine);
429
+ int psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
430
+
431
+ /*
432
+ * If the user provides an Operating System to be loaded, we expect them
433
+ * to use the -kernel command line option.
434
+ *
435
+ * Users can load firmware or boot-loaders with the -device loader options.
436
+ *
437
+ * When loading an OS, we generate a dtb and let arm_load_kernel() select
438
+ * where it gets loaded. This dtb will be passed to the kernel in x0.
439
+ *
440
+ * If there's no -kernel option, we generate a DTB and place it at 0x1000
441
+ * for the bootloaders or firmware to pick up.
442
+ *
443
+ * If users want to provide their own DTB, they can use the -dtb option.
444
+ * These dtb's will have their memory nodes modified to match QEMU's
445
+ * selected ram_size option before they get passed to the kernel or fw.
446
+ *
447
+ * When loading an OS, we turn on QEMU's PSCI implementation with SMC
448
+ * as the PSCI conduit. When there's no -kernel, we assume the user
449
+ * provides EL3 firmware to handle PSCI.
450
+ */
451
+ if (machine->kernel_filename) {
452
+ psci_conduit = QEMU_PSCI_CONDUIT_SMC;
453
+ }
454
+
455
+ memory_region_allocate_system_memory(&s->mr_ddr, NULL, "ddr",
456
+ machine->ram_size);
457
+
458
+ sysbus_init_child_obj(OBJECT(machine), "xlnx-ve", &s->soc,
459
+ sizeof(s->soc), TYPE_XLNX_VERSAL);
460
+ object_property_set_link(OBJECT(&s->soc), OBJECT(&s->mr_ddr),
461
+ "ddr", &error_abort);
462
+ object_property_set_int(OBJECT(&s->soc), psci_conduit,
463
+ "psci-conduit", &error_abort);
464
+ object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_fatal);
465
+
466
+ fdt_create(s);
467
+ create_virtio_regions(s);
468
+ fdt_add_gem_nodes(s);
469
+ fdt_add_uart_nodes(s);
470
+ fdt_add_gic_nodes(s);
471
+ fdt_add_timer_nodes(s);
472
+ fdt_add_cpu_nodes(s, psci_conduit);
473
+ fdt_add_clk_node(s, "/clk125", 125000000, s->phandle.clk_125Mhz);
474
+ fdt_add_clk_node(s, "/clk25", 25000000, s->phandle.clk_25Mhz);
475
+
476
+ /* Make the APU cpu address space visible to virtio and other
477
+ * modules unaware of muliple address-spaces. */
478
+ memory_region_add_subregion_overlap(get_system_memory(),
479
+ 0, &s->soc.fpd.apu.mr, 0);
480
+
481
+ s->binfo.ram_size = machine->ram_size;
482
+ s->binfo.kernel_filename = machine->kernel_filename;
483
+ s->binfo.kernel_cmdline = machine->kernel_cmdline;
484
+ s->binfo.initrd_filename = machine->initrd_filename;
485
+ s->binfo.loader_start = 0x0;
486
+ s->binfo.get_dtb = versal_virt_get_dtb;
487
+ s->binfo.modify_dtb = versal_virt_modify_dtb;
488
+ if (machine->kernel_filename) {
489
+ arm_load_kernel(s->soc.fpd.apu.cpu[0], &s->binfo);
490
+ } else {
491
+ AddressSpace *as = arm_boot_address_space(s->soc.fpd.apu.cpu[0],
492
+ &s->binfo);
493
+ /* Some boot-loaders (e.g u-boot) don't like blobs at address 0 (NULL).
494
+ * Offset things by 4K. */
495
+ s->binfo.loader_start = 0x1000;
496
+ s->binfo.dtb_limit = 0x1000000;
497
+ if (arm_load_dtb(s->binfo.loader_start,
498
+ &s->binfo, s->binfo.dtb_limit, as) < 0) {
499
+ exit(EXIT_FAILURE);
500
+ }
501
+ }
502
+}
503
+
504
+static void versal_virt_machine_instance_init(Object *obj)
505
+{
506
+}
507
+
508
+static void versal_virt_machine_class_init(ObjectClass *oc, void *data)
509
+{
510
+ MachineClass *mc = MACHINE_CLASS(oc);
511
+
512
+ mc->desc = "Xilinx Versal Virtual development board";
513
+ mc->init = versal_virt_init;
514
+ mc->max_cpus = XLNX_VERSAL_NR_ACPUS;
515
+ mc->default_cpus = XLNX_VERSAL_NR_ACPUS;
516
+ mc->no_cdrom = true;
517
+}
518
+
519
+static const TypeInfo versal_virt_machine_init_typeinfo = {
520
+ .name = TYPE_XLNX_VERSAL_VIRT_MACHINE,
521
+ .parent = TYPE_MACHINE,
522
+ .class_init = versal_virt_machine_class_init,
523
+ .instance_init = versal_virt_machine_instance_init,
524
+ .instance_size = sizeof(VersalVirt),
525
+};
526
+
527
+static void versal_virt_machine_init_register_types(void)
528
+{
529
+ type_register_static(&versal_virt_machine_init_typeinfo);
530
+}
531
+
532
+type_init(versal_virt_machine_init_register_types)
533
+
364
--
534
--
365
2.25.1
535
2.19.1
536
537
diff view generated by jsdifflib
Deleted patch
1
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
2
1
3
When the system reboots, the rng-seed that the FDT has should be
4
re-randomized, so that the new boot gets a new seed. Several
5
architectures require this functionality, so export a function for
6
injecting a new seed into the given FDT.
7
8
Cc: Alistair Francis <alistair.francis@wdc.com>
9
Cc: David Gibson <david@gibson.dropbear.id.au>
10
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
11
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
12
Message-id: 20221025004327.568476-3-Jason@zx2c4.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
include/sysemu/device_tree.h | 9 +++++++++
16
softmmu/device_tree.c | 21 +++++++++++++++++++++
17
2 files changed, 30 insertions(+)
18
19
diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/sysemu/device_tree.h
22
+++ b/include/sysemu/device_tree.h
23
@@ -XXX,XX +XXX,XX @@ int qemu_fdt_setprop_sized_cells_from_array(void *fdt,
24
qdt_tmp); \
25
})
26
27
+
28
+/**
29
+ * qemu_fdt_randomize_seeds:
30
+ * @fdt: device tree blob
31
+ *
32
+ * Re-randomize all "rng-seed" properties with new seeds.
33
+ */
34
+void qemu_fdt_randomize_seeds(void *fdt);
35
+
36
#define FDT_PCI_RANGE_RELOCATABLE 0x80000000
37
#define FDT_PCI_RANGE_PREFETCHABLE 0x40000000
38
#define FDT_PCI_RANGE_ALIASED 0x20000000
39
diff --git a/softmmu/device_tree.c b/softmmu/device_tree.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/softmmu/device_tree.c
42
+++ b/softmmu/device_tree.c
43
@@ -XXX,XX +XXX,XX @@
44
#include "qemu/option.h"
45
#include "qemu/bswap.h"
46
#include "qemu/cutils.h"
47
+#include "qemu/guest-random.h"
48
#include "sysemu/device_tree.h"
49
#include "hw/loader.h"
50
#include "hw/boards.h"
51
@@ -XXX,XX +XXX,XX @@ void hmp_dumpdtb(Monitor *mon, const QDict *qdict)
52
53
info_report("dtb dumped to %s", filename);
54
}
55
+
56
+void qemu_fdt_randomize_seeds(void *fdt)
57
+{
58
+ int noffset, poffset, len;
59
+ const char *name;
60
+ uint8_t *data;
61
+
62
+ for (noffset = fdt_next_node(fdt, 0, NULL);
63
+ noffset >= 0;
64
+ noffset = fdt_next_node(fdt, noffset, NULL)) {
65
+ for (poffset = fdt_first_property_offset(fdt, noffset);
66
+ poffset >= 0;
67
+ poffset = fdt_next_property_offset(fdt, poffset)) {
68
+ data = (uint8_t *)fdt_getprop_by_offset(fdt, poffset, &name, &len);
69
+ if (!data || strcmp(name, "rng-seed"))
70
+ continue;
71
+ qemu_guest_getrandom_nofail(data, len);
72
+ }
73
+ }
74
+}
75
--
76
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
2
1
3
Snapshot loading is supposed to be deterministic, so we shouldn't
4
re-randomize the various seeds used.
5
6
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
7
Message-id: 20221025004327.568476-4-Jason@zx2c4.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/i386/x86.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/i386/x86.c
17
+++ b/hw/i386/x86.c
18
@@ -XXX,XX +XXX,XX @@ void x86_load_linux(X86MachineState *x86ms,
19
setup_data->type = cpu_to_le32(SETUP_RNG_SEED);
20
setup_data->len = cpu_to_le32(RNG_SEED_LENGTH);
21
qemu_guest_getrandom_nofail(setup_data->data, RNG_SEED_LENGTH);
22
- qemu_register_reset(reset_rng_seed, setup_data);
23
+ qemu_register_reset_nosnapshotload(reset_rng_seed, setup_data);
24
fw_cfg_add_bytes_callback(fw_cfg, FW_CFG_KERNEL_DATA, reset_rng_seed, NULL,
25
setup_data, kernel, kernel_size, true);
26
} else {
27
--
28
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
2
1
3
When the system reboots, the rng-seed that the FDT has should be
4
re-randomized, so that the new boot gets a new seed. Since the FDT is in
5
the ROM region at this point, we add a hook right after the ROM has been
6
added, so that we have a pointer to that copy of the FDT.
7
8
Cc: Palmer Dabbelt <palmer@dabbelt.com>
9
Cc: Alistair Francis <alistair.francis@wdc.com>
10
Cc: Bin Meng <bin.meng@windriver.com>
11
Cc: qemu-riscv@nongnu.org
12
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
14
Message-id: 20221025004327.568476-6-Jason@zx2c4.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
hw/riscv/boot.c | 3 +++
18
1 file changed, 3 insertions(+)
19
20
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/riscv/boot.c
23
+++ b/hw/riscv/boot.c
24
@@ -XXX,XX +XXX,XX @@
25
#include "sysemu/device_tree.h"
26
#include "sysemu/qtest.h"
27
#include "sysemu/kvm.h"
28
+#include "sysemu/reset.h"
29
30
#include <libfdt.h>
31
32
@@ -XXX,XX +XXX,XX @@ uint64_t riscv_load_fdt(hwaddr dram_base, uint64_t mem_size, void *fdt)
33
34
rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr,
35
&address_space_memory);
36
+ qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
37
+ rom_ptr_for_as(&address_space_memory, fdt_addr, fdtsize));
38
39
return fdt_addr;
40
}
41
--
42
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
2
1
3
Snapshot loading is supposed to be deterministic, so we shouldn't
4
re-randomize the various seeds used.
5
6
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
7
Message-id: 20221025004327.568476-7-Jason@zx2c4.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/m68k/virt.c | 20 +++++++++++---------
12
1 file changed, 11 insertions(+), 9 deletions(-)
13
14
diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/m68k/virt.c
17
+++ b/hw/m68k/virt.c
18
@@ -XXX,XX +XXX,XX @@ typedef struct {
19
M68kCPU *cpu;
20
hwaddr initial_pc;
21
hwaddr initial_stack;
22
- struct bi_record *rng_seed;
23
} ResetInfo;
24
25
static void main_cpu_reset(void *opaque)
26
@@ -XXX,XX +XXX,XX @@ static void main_cpu_reset(void *opaque)
27
M68kCPU *cpu = reset_info->cpu;
28
CPUState *cs = CPU(cpu);
29
30
- if (reset_info->rng_seed) {
31
- qemu_guest_getrandom_nofail((void *)reset_info->rng_seed->data + 2,
32
- be16_to_cpu(*(uint16_t *)reset_info->rng_seed->data));
33
- }
34
-
35
cpu_reset(cs);
36
cpu->env.aregs[7] = reset_info->initial_stack;
37
cpu->env.pc = reset_info->initial_pc;
38
}
39
40
+static void rerandomize_rng_seed(void *opaque)
41
+{
42
+ struct bi_record *rng_seed = opaque;
43
+ qemu_guest_getrandom_nofail((void *)rng_seed->data + 2,
44
+ be16_to_cpu(*(uint16_t *)rng_seed->data));
45
+}
46
+
47
static void virt_init(MachineState *machine)
48
{
49
M68kCPU *cpu = NULL;
50
@@ -XXX,XX +XXX,XX @@ static void virt_init(MachineState *machine)
51
BOOTINFO0(param_ptr, BI_LAST);
52
rom_add_blob_fixed_as("bootinfo", param_blob, param_ptr - param_blob,
53
parameters_base, cs->as);
54
- reset_info->rng_seed = rom_ptr_for_as(cs->as, parameters_base,
55
- param_ptr - param_blob) +
56
- (param_rng_seed - param_blob);
57
+ qemu_register_reset_nosnapshotload(rerandomize_rng_seed,
58
+ rom_ptr_for_as(cs->as, parameters_base,
59
+ param_ptr - param_blob) +
60
+ (param_rng_seed - param_blob));
61
g_free(param_blob);
62
}
63
}
64
--
65
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
2
1
3
Snapshot loading is supposed to be deterministic, so we shouldn't
4
re-randomize the various seeds used.
5
6
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
7
Message-id: 20221025004327.568476-8-Jason@zx2c4.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/m68k/q800.c | 33 +++++++++++++--------------------
12
1 file changed, 13 insertions(+), 20 deletions(-)
13
14
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/m68k/q800.c
17
+++ b/hw/m68k/q800.c
18
@@ -XXX,XX +XXX,XX @@ static const TypeInfo glue_info = {
19
},
20
};
21
22
-typedef struct {
23
- M68kCPU *cpu;
24
- struct bi_record *rng_seed;
25
-} ResetInfo;
26
-
27
static void main_cpu_reset(void *opaque)
28
{
29
- ResetInfo *reset_info = opaque;
30
- M68kCPU *cpu = reset_info->cpu;
31
+ M68kCPU *cpu = opaque;
32
CPUState *cs = CPU(cpu);
33
34
- if (reset_info->rng_seed) {
35
- qemu_guest_getrandom_nofail((void *)reset_info->rng_seed->data + 2,
36
- be16_to_cpu(*(uint16_t *)reset_info->rng_seed->data));
37
- }
38
-
39
cpu_reset(cs);
40
cpu->env.aregs[7] = ldl_phys(cs->as, 0);
41
cpu->env.pc = ldl_phys(cs->as, 4);
42
}
43
44
+static void rerandomize_rng_seed(void *opaque)
45
+{
46
+ struct bi_record *rng_seed = opaque;
47
+ qemu_guest_getrandom_nofail((void *)rng_seed->data + 2,
48
+ be16_to_cpu(*(uint16_t *)rng_seed->data));
49
+}
50
+
51
static uint8_t fake_mac_rom[] = {
52
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53
54
@@ -XXX,XX +XXX,XX @@ static void q800_init(MachineState *machine)
55
NubusBus *nubus;
56
DeviceState *glue;
57
DriveInfo *dinfo;
58
- ResetInfo *reset_info;
59
uint8_t rng_seed[32];
60
61
linux_boot = (kernel_filename != NULL);
62
@@ -XXX,XX +XXX,XX @@ static void q800_init(MachineState *machine)
63
exit(1);
64
}
65
66
- reset_info = g_new0(ResetInfo, 1);
67
-
68
/* init CPUs */
69
cpu = M68K_CPU(cpu_create(machine->cpu_type));
70
- reset_info->cpu = cpu;
71
- qemu_register_reset(main_cpu_reset, reset_info);
72
+ qemu_register_reset(main_cpu_reset, cpu);
73
74
/* RAM */
75
memory_region_add_subregion(get_system_memory(), 0, machine->ram);
76
@@ -XXX,XX +XXX,XX @@ static void q800_init(MachineState *machine)
77
BOOTINFO0(param_ptr, BI_LAST);
78
rom_add_blob_fixed_as("bootinfo", param_blob, param_ptr - param_blob,
79
parameters_base, cs->as);
80
- reset_info->rng_seed = rom_ptr_for_as(cs->as, parameters_base,
81
- param_ptr - param_blob) +
82
- (param_rng_seed - param_blob);
83
+ qemu_register_reset_nosnapshotload(rerandomize_rng_seed,
84
+ rom_ptr_for_as(cs->as, parameters_base,
85
+ param_ptr - param_blob) +
86
+ (param_rng_seed - param_blob));
87
g_free(param_blob);
88
} else {
89
uint8_t *ptr;
90
--
91
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
2
1
3
When the system reboots, the rng-seed that the FDT has should be
4
re-randomized, so that the new boot gets a new seed. Since the FDT is in
5
the ROM region at this point, we add a hook right after the ROM has been
6
added, so that we have a pointer to that copy of the FDT.
7
8
Cc: Stafford Horne <shorne@gmail.com>
9
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
10
Message-id: 20221025004327.568476-11-Jason@zx2c4.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
hw/openrisc/boot.c | 3 +++
15
1 file changed, 3 insertions(+)
16
17
diff --git a/hw/openrisc/boot.c b/hw/openrisc/boot.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/openrisc/boot.c
20
+++ b/hw/openrisc/boot.c
21
@@ -XXX,XX +XXX,XX @@
22
#include "hw/openrisc/boot.h"
23
#include "sysemu/device_tree.h"
24
#include "sysemu/qtest.h"
25
+#include "sysemu/reset.h"
26
27
#include <libfdt.h>
28
29
@@ -XXX,XX +XXX,XX @@ uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start,
30
31
rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr,
32
&address_space_memory);
33
+ qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
34
+ rom_ptr_for_as(&address_space_memory, fdt_addr, fdtsize));
35
36
return fdt_addr;
37
}
38
--
39
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
2
1
3
When the system reboots, the rng-seed that the FDT has should be
4
re-randomized, so that the new boot gets a new seed. Since the FDT is in
5
the ROM region at this point, we add a hook right after the ROM has been
6
added, so that we have a pointer to that copy of the FDT.
7
8
Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
9
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
10
Message-id: 20221025004327.568476-12-Jason@zx2c4.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
hw/rx/rx-gdbsim.c | 3 +++
15
1 file changed, 3 insertions(+)
16
17
diff --git a/hw/rx/rx-gdbsim.c b/hw/rx/rx-gdbsim.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/rx/rx-gdbsim.c
20
+++ b/hw/rx/rx-gdbsim.c
21
@@ -XXX,XX +XXX,XX @@
22
#include "hw/rx/rx62n.h"
23
#include "sysemu/qtest.h"
24
#include "sysemu/device_tree.h"
25
+#include "sysemu/reset.h"
26
#include "hw/boards.h"
27
#include "qom/object.h"
28
29
@@ -XXX,XX +XXX,XX @@ static void rx_gdbsim_init(MachineState *machine)
30
dtb_offset = ROUND_DOWN(machine->ram_size - dtb_size, 16);
31
rom_add_blob_fixed("dtb", dtb, dtb_size,
32
SDRAM_BASE + dtb_offset);
33
+ qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
34
+ rom_ptr(SDRAM_BASE + dtb_offset, dtb_size));
35
/* Set dtb address to R1 */
36
RX_CPU(first_cpu)->env.regs[1] = SDRAM_BASE + dtb_offset;
37
}
38
--
39
2.25.1
diff view generated by jsdifflib