1
target-arm queue for softfreeze:
1
Two small bugfixes, plus most of RTH's refactoring of cpregs
2
This has all the big stuff I want to get in for softfreeze;
2
handling.
3
there may be one or two smaller patches I pick up later in
4
the week.
5
3
6
thanks
7
-- PMM
4
-- PMM
8
5
9
The following changes since commit 0984a157c1c053394adbf64ed7de97f1aebe6a2d:
6
The following changes since commit 1fba9dc71a170b3a05b9d3272dd8ecfe7f26e215:
10
7
11
Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging (2019-03-05 09:33:20 +0000)
8
Merge tag 'pull-request-2022-05-04' of https://gitlab.com/thuth/qemu into staging (2022-05-04 08:07:02 -0700)
12
9
13
are available in the Git repository at:
10
are available in the Git repository at:
14
11
15
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190305
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220505
16
13
17
for you to fetch changes up to 566528f823d1a2e9eb2d7b2ed839547cb31bfc34:
14
for you to fetch changes up to 99a50d1a67c602126fc2b3a4812d3000eba9bf34:
18
15
19
hw/arm/stellaris: Implement watchdog timer (2019-03-05 15:55:09 +0000)
16
target/arm: read access to performance counters from EL0 (2022-05-05 09:36:22 +0100)
20
17
21
----------------------------------------------------------------
18
----------------------------------------------------------------
22
target-arm queue:
19
target-arm queue:
23
* Fix PC test for LDM (exception return)
20
* Enable read access to performance counters from EL0
24
* Implement ARMv8.0-SB
21
* Enable SCTLR_EL1.BT0 for aarch64-linux-user
25
* Implement ARMv8.0-PredInv
22
* Refactoring of cpreg handling
26
* Implement ARMv8.4-CondM
27
* Implement ARMv8.5-CondM
28
* Implement ARMv8.5-FRINT
29
* hw/arm/stellaris: Implement watchdog timer
30
* virt: support more than 255GB of RAM
31
23
32
----------------------------------------------------------------
24
----------------------------------------------------------------
33
Eric Auger (9):
25
Alex Zuepke (1):
34
hw/arm/virt: Rename highmem IO regions
26
target/arm: read access to performance counters from EL0
35
hw/arm/virt: Split the memory map description
36
hw/boards: Add a MachineState parameter to kvm_type callback
37
kvm: add kvm_arm_get_max_vm_ipa_size
38
vl: Set machine ram_size, maxram_size and ram_slots earlier
39
hw/arm/virt: Dynamic memory map depending on RAM requirements
40
hw/arm/virt: Implement kvm_type function for 4.0 machine
41
hw/arm/virt: Check the VCPU PA range in TCG mode
42
hw/arm/virt: Bump the 255GB initial RAM limit
43
27
44
Michel Heily (1):
28
Richard Henderson (22):
45
hw/arm/stellaris: Implement watchdog timer
29
target/arm: Enable SCTLR_EL1.BT0 for aarch64-linux-user
30
target/arm: Split out cpregs.h
31
target/arm: Reorg CPAccessResult and access_check_cp_reg
32
target/arm: Replace sentinels with ARRAY_SIZE in cpregs.h
33
target/arm: Make some more cpreg data static const
34
target/arm: Reorg ARMCPRegInfo type field bits
35
target/arm: Avoid bare abort() or assert(0)
36
target/arm: Change cpreg access permissions to enum
37
target/arm: Name CPState type
38
target/arm: Name CPSecureState type
39
target/arm: Drop always-true test in define_arm_vh_e2h_redirects_aliases
40
target/arm: Store cpregs key in the hash table directly
41
target/arm: Merge allocation of the cpreg and its name
42
target/arm: Hoist computation of key in add_cpreg_to_hashtable
43
target/arm: Consolidate cpreg updates in add_cpreg_to_hashtable
44
target/arm: Use bool for is64 and ns in add_cpreg_to_hashtable
45
target/arm: Hoist isbanked computation in add_cpreg_to_hashtable
46
target/arm: Perform override check early in add_cpreg_to_hashtable
47
target/arm: Reformat comments in add_cpreg_to_hashtable
48
target/arm: Remove HOST_BIG_ENDIAN ifdef in add_cpreg_to_hashtable
49
target/arm: Add isar predicates for FEAT_Debugv8p2
50
target/arm: Add isar_feature_{aa64,any}_ras
46
51
47
Richard Henderson (11):
52
target/arm/cpregs.h | 453 ++++++++++++++++++++++++++++++++++++++
48
target/arm: Fix PC test for LDM (exception return)
53
target/arm/cpu.h | 393 +++------------------------------
49
target/arm: Split out arm_sctlr
54
hw/arm/pxa2xx.c | 2 +-
50
target/arm: Implement ARMv8.0-SB
55
hw/arm/pxa2xx_pic.c | 2 +-
51
target/arm: Implement ARMv8.0-PredInv
56
hw/intc/arm_gicv3_cpuif.c | 6 +-
52
target/arm: Split helper_msr_i_pstate into 3
57
hw/intc/arm_gicv3_kvm.c | 3 +-
53
target/arm: Add set/clear_pstate_bits, share gen_ss_advance
58
target/arm/cpu.c | 25 +--
54
target/arm: Rearrange disas_data_proc_reg
59
target/arm/cpu64.c | 2 +-
55
target/arm: Implement ARMv8.4-CondM
60
target/arm/cpu_tcg.c | 5 +-
56
target/arm: Implement ARMv8.5-CondM
61
target/arm/gdbstub.c | 5 +-
57
target/arm: Restructure handle_fp_1src_{single, double}
62
target/arm/helper.c | 358 +++++++++++++-----------------
58
target/arm: Implement ARMv8.5-FRINT
63
target/arm/hvf/hvf.c | 2 +-
59
64
target/arm/kvm-stub.c | 4 +-
60
Shameer Kolothum (1):
65
target/arm/kvm.c | 4 +-
61
hw/arm/boot: introduce fdt_add_memory_node helper
66
target/arm/machine.c | 4 +-
62
67
target/arm/op_helper.c | 57 ++---
63
include/hw/arm/virt.h | 16 +-
68
target/arm/translate-a64.c | 14 +-
64
include/hw/boards.h | 5 +-
69
target/arm/translate-neon.c | 2 +-
65
include/hw/watchdog/cmsdk-apb-watchdog.h | 8 +
70
target/arm/translate.c | 13 +-
66
target/arm/cpu.h | 64 ++++-
71
tests/tcg/aarch64/bti-3.c | 42 ++++
67
target/arm/helper-a64.h | 3 +
72
tests/tcg/aarch64/Makefile.target | 6 +-
68
target/arm/helper.h | 8 +-
73
21 files changed, 738 insertions(+), 664 deletions(-)
69
target/arm/internals.h | 15 +
74
create mode 100644 target/arm/cpregs.h
70
target/arm/kvm_arm.h | 13 +
75
create mode 100644 tests/tcg/aarch64/bti-3.c
71
target/arm/translate.h | 34 +++
72
accel/kvm/kvm-all.c | 2 +-
73
hw/arm/boot.c | 54 ++--
74
hw/arm/stellaris.c | 22 +-
75
hw/arm/virt-acpi-build.c | 10 +-
76
hw/arm/virt.c | 196 ++++++++++---
77
hw/ppc/mac_newworld.c | 3 +-
78
hw/ppc/mac_oldworld.c | 2 +-
79
hw/ppc/spapr.c | 2 +-
80
hw/watchdog/cmsdk-apb-watchdog.c | 74 ++++-
81
linux-user/elfload.c | 2 +
82
target/arm/cpu.c | 2 +
83
target/arm/cpu64.c | 6 +
84
target/arm/helper-a64.c | 30 ++
85
target/arm/helper.c | 63 +++-
86
target/arm/kvm.c | 10 +
87
target/arm/op_helper.c | 47 ---
88
target/arm/translate-a64.c | 478 +++++++++++++++++++++++--------
89
target/arm/translate.c | 35 ++-
90
target/arm/vfp_helper.c | 96 +++++++
91
vl.c | 6 +-
92
29 files changed, 1032 insertions(+), 274 deletions(-)
93
diff view generated by jsdifflib
1
From: Michel Heily <michelheily@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Implement the watchdog timer for the stellaris boards.
3
This controls whether the PACI{A,B}SP instructions trap with BTYPE=3
4
This device is a close variant of the CMSDK APB watchdog
4
(indirect branch from register other than x16/x17). The linux kernel
5
device, so we can model it by subclassing that device and
5
sets this in bti_enable().
6
tweaking the behaviour of some of its registers.
7
6
8
Signed-off-by: Michel Heily <michelheily@gmail.com>
7
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/998
9
Reviewed-by: Peter Maydell <petser.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
[PMM: rewrote commit message, fixed a few checkpatch nits,
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
added comment giving the URL of the spec for the Stellaris
10
Message-id: 20220427042312.294300-1-richard.henderson@linaro.org
12
variant of the watchdog device]
11
[PMM: remove stray change to makefile comment]
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
13
---
15
include/hw/watchdog/cmsdk-apb-watchdog.h | 8 +++
14
target/arm/cpu.c | 2 ++
16
hw/arm/stellaris.c | 22 ++++++-
15
tests/tcg/aarch64/bti-3.c | 42 +++++++++++++++++++++++++++++++
17
hw/watchdog/cmsdk-apb-watchdog.c | 74 +++++++++++++++++++++++-
16
tests/tcg/aarch64/Makefile.target | 6 ++---
18
3 files changed, 100 insertions(+), 4 deletions(-)
17
3 files changed, 47 insertions(+), 3 deletions(-)
18
create mode 100644 tests/tcg/aarch64/bti-3.c
19
19
20
diff --git a/include/hw/watchdog/cmsdk-apb-watchdog.h b/include/hw/watchdog/cmsdk-apb-watchdog.h
20
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
21
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/watchdog/cmsdk-apb-watchdog.h
22
--- a/target/arm/cpu.c
23
+++ b/include/hw/watchdog/cmsdk-apb-watchdog.h
23
+++ b/target/arm/cpu.c
24
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
25
/* Enable all PAC keys. */
26
env->cp15.sctlr_el[1] |= (SCTLR_EnIA | SCTLR_EnIB |
27
SCTLR_EnDA | SCTLR_EnDB);
28
+ /* Trap on btype=3 for PACIxSP. */
29
+ env->cp15.sctlr_el[1] |= SCTLR_BT0;
30
/* and to the FP/Neon instructions */
31
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 20, 2, 3);
32
/* and to the SVE instructions */
33
diff --git a/tests/tcg/aarch64/bti-3.c b/tests/tcg/aarch64/bti-3.c
34
new file mode 100644
35
index XXXXXXX..XXXXXXX
36
--- /dev/null
37
+++ b/tests/tcg/aarch64/bti-3.c
24
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@
25
#define CMSDK_APB_WATCHDOG(obj) OBJECT_CHECK(CMSDKAPBWatchdog, (obj), \
26
TYPE_CMSDK_APB_WATCHDOG)
27
28
+/*
39
+/*
29
+ * This shares the same struct (and cast macro) as the base
40
+ * BTI vs PACIASP
30
+ * cmsdk-apb-watchdog device.
31
+ */
41
+ */
32
+#define TYPE_LUMINARY_WATCHDOG "luminary-watchdog"
33
+
42
+
34
typedef struct CMSDKAPBWatchdog {
43
+#include "bti-crt.inc.c"
35
/*< private >*/
36
SysBusDevice parent_obj;
37
@@ -XXX,XX +XXX,XX @@ typedef struct CMSDKAPBWatchdog {
38
MemoryRegion iomem;
39
qemu_irq wdogint;
40
uint32_t wdogclk_frq;
41
+ bool is_luminary;
42
struct ptimer_state *timer;
43
44
uint32_t control;
45
@@ -XXX,XX +XXX,XX @@ typedef struct CMSDKAPBWatchdog {
46
uint32_t itcr;
47
uint32_t itop;
48
uint32_t resetstatus;
49
+ const uint32_t *id;
50
} CMSDKAPBWatchdog;
51
52
#endif
53
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/hw/arm/stellaris.c
56
+++ b/hw/arm/stellaris.c
57
@@ -XXX,XX +XXX,XX @@
58
#include "sysemu/sysemu.h"
59
#include "hw/arm/armv7m.h"
60
#include "hw/char/pl011.h"
61
+#include "hw/watchdog/cmsdk-apb-watchdog.h"
62
#include "hw/misc/unimp.h"
63
#include "cpu.h"
64
65
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
66
* Stellaris LM3S6965 Microcontroller Data Sheet (rev I)
67
* http://www.ti.com/lit/ds/symlink/lm3s6965.pdf
68
*
69
- * 40000000 wdtimer (unimplemented)
70
+ * 40000000 wdtimer
71
* 40002000 i2c (unimplemented)
72
* 40004000 GPIO
73
* 40005000 GPIO
74
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
75
stellaris_sys_init(0x400fe000, qdev_get_gpio_in(nvic, 28),
76
board, nd_table[0].macaddr.a);
77
78
+
44
+
79
+ if (board->dc1 & (1 << 3)) { /* watchdog present */
45
+static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc)
80
+ dev = qdev_create(NULL, TYPE_LUMINARY_WATCHDOG);
81
+
82
+ /* system_clock_scale is valid now */
83
+ uint32_t mainclk = NANOSECONDS_PER_SECOND / system_clock_scale;
84
+ qdev_prop_set_uint32(dev, "wdogclk-frq", mainclk);
85
+
86
+ qdev_init_nofail(dev);
87
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev),
88
+ 0,
89
+ 0x40000000u);
90
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev),
91
+ 0,
92
+ qdev_get_gpio_in(nvic, 18));
93
+ }
94
+
95
+
96
for (i = 0; i < 7; i++) {
97
if (board->dc4 & (1 << i)) {
98
gpio_dev[i] = sysbus_create_simple("pl061_luminary", gpio_addr[i],
99
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
100
/* Add dummy regions for the devices we don't implement yet,
101
* so guest accesses don't cause unlogged crashes.
102
*/
103
- create_unimplemented_device("wdtimer", 0x40000000, 0x1000);
104
create_unimplemented_device("i2c-0", 0x40002000, 0x1000);
105
create_unimplemented_device("i2c-2", 0x40021000, 0x1000);
106
create_unimplemented_device("PWM", 0x40028000, 0x1000);
107
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/hw/watchdog/cmsdk-apb-watchdog.c
110
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
111
@@ -XXX,XX +XXX,XX @@
112
* System Design Kit (CMSDK) and documented in the Cortex-M System
113
* Design Kit Technical Reference Manual (ARM DDI0479C):
114
* https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
115
+ *
116
+ * We also support the variant of this device found in the TI
117
+ * Stellaris/Luminary boards and documented in:
118
+ * http://www.ti.com/lit/ds/symlink/lm3s6965.pdf
119
*/
120
121
#include "qemu/osdep.h"
122
@@ -XXX,XX +XXX,XX @@ REG32(WDOGINTCLR, 0xc)
123
REG32(WDOGRIS, 0x10)
124
FIELD(WDOGRIS, INT, 0, 1)
125
REG32(WDOGMIS, 0x14)
126
+REG32(WDOGTEST, 0x418) /* only in Stellaris/Luminary version of the device */
127
REG32(WDOGLOCK, 0xc00)
128
#define WDOG_UNLOCK_VALUE 0x1ACCE551
129
REG32(WDOGITCR, 0xf00)
130
@@ -XXX,XX +XXX,XX @@ REG32(CID2, 0xff8)
131
REG32(CID3, 0xffc)
132
133
/* PID/CID values */
134
-static const int watchdog_id[] = {
135
+static const uint32_t cmsdk_apb_watchdog_id[] = {
136
0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
137
0x24, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
138
0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
139
};
140
141
+static const uint32_t luminary_watchdog_id[] = {
142
+ 0x00, 0x00, 0x00, 0x00, /* PID4..PID7 */
143
+ 0x05, 0x18, 0x18, 0x01, /* PID0..PID3 */
144
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
145
+};
146
+
147
static bool cmsdk_apb_watchdog_intstatus(CMSDKAPBWatchdog *s)
148
{
149
/* Return masked interrupt status */
150
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_update(CMSDKAPBWatchdog *s)
151
bool wdogres;
152
153
if (s->itcr) {
154
+ /*
155
+ * Not checking that !s->is_luminary since s->itcr can't be written
156
+ * when s->is_luminary in the first place.
157
+ */
158
wdogint = s->itop & R_WDOGITOP_WDOGINT_MASK;
159
wdogres = s->itop & R_WDOGITOP_WDOGRES_MASK;
160
} else {
161
@@ -XXX,XX +XXX,XX @@ static uint64_t cmsdk_apb_watchdog_read(void *opaque, hwaddr offset,
162
r = s->lock;
163
break;
164
case A_WDOGITCR:
165
+ if (s->is_luminary) {
166
+ goto bad_offset;
167
+ }
168
r = s->itcr;
169
break;
170
case A_PID4 ... A_CID3:
171
- r = watchdog_id[(offset - A_PID4) / 4];
172
+ r = s->id[(offset - A_PID4) / 4];
173
break;
174
case A_WDOGINTCLR:
175
case A_WDOGITOP:
176
+ if (s->is_luminary) {
177
+ goto bad_offset;
178
+ }
179
qemu_log_mask(LOG_GUEST_ERROR,
180
"CMSDK APB watchdog read: read of WO offset %x\n",
181
(int)offset);
182
r = 0;
183
break;
184
+ case A_WDOGTEST:
185
+ if (!s->is_luminary) {
186
+ goto bad_offset;
187
+ }
188
+ qemu_log_mask(LOG_UNIMP,
189
+ "Luminary watchdog read: stall not implemented\n");
190
+ r = 0;
191
+ break;
192
default:
193
+bad_offset:
194
qemu_log_mask(LOG_GUEST_ERROR,
195
"CMSDK APB watchdog read: bad offset %x\n", (int)offset);
196
r = 0;
197
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_write(void *opaque, hwaddr offset,
198
ptimer_run(s->timer, 0);
199
break;
200
case A_WDOGCONTROL:
201
+ if (s->is_luminary && 0 != (R_WDOGCONTROL_INTEN_MASK & s->control)) {
202
+ /*
203
+ * The Luminary version of this device ignores writes to
204
+ * this register after the guest has enabled interrupts
205
+ * (so they can only be disabled again via reset).
206
+ */
207
+ break;
208
+ }
209
s->control = value & R_WDOGCONTROL_VALID_MASK;
210
cmsdk_apb_watchdog_update(s);
211
break;
212
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_write(void *opaque, hwaddr offset,
213
s->lock = (value != WDOG_UNLOCK_VALUE);
214
break;
215
case A_WDOGITCR:
216
+ if (s->is_luminary) {
217
+ goto bad_offset;
218
+ }
219
s->itcr = value & R_WDOGITCR_VALID_MASK;
220
cmsdk_apb_watchdog_update(s);
221
break;
222
case A_WDOGITOP:
223
+ if (s->is_luminary) {
224
+ goto bad_offset;
225
+ }
226
s->itop = value & R_WDOGITOP_VALID_MASK;
227
cmsdk_apb_watchdog_update(s);
228
break;
229
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_write(void *opaque, hwaddr offset,
230
"CMSDK APB watchdog write: write to RO offset 0x%x\n",
231
(int)offset);
232
break;
233
+ case A_WDOGTEST:
234
+ if (!s->is_luminary) {
235
+ goto bad_offset;
236
+ }
237
+ qemu_log_mask(LOG_UNIMP,
238
+ "Luminary watchdog write: stall not implemented\n");
239
+ break;
240
default:
241
+bad_offset:
242
qemu_log_mask(LOG_GUEST_ERROR,
243
"CMSDK APB watchdog write: bad offset 0x%x\n",
244
(int)offset);
245
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_init(Object *obj)
246
s, "cmsdk-apb-watchdog", 0x1000);
247
sysbus_init_mmio(sbd, &s->iomem);
248
sysbus_init_irq(sbd, &s->wdogint);
249
+
250
+ s->is_luminary = false;
251
+ s->id = cmsdk_apb_watchdog_id;
252
}
253
254
static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
255
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cmsdk_apb_watchdog_info = {
256
.class_init = cmsdk_apb_watchdog_class_init,
257
};
258
259
+static void luminary_watchdog_init(Object *obj)
260
+{
46
+{
261
+ CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(obj);
47
+ uc->uc_mcontext.pc += 8;
262
+
48
+ uc->uc_mcontext.pstate = 1;
263
+ s->is_luminary = true;
264
+ s->id = luminary_watchdog_id;
265
+}
49
+}
266
+
50
+
267
+static const TypeInfo luminary_watchdog_info = {
51
+#define BTYPE_1() \
268
+ .name = TYPE_LUMINARY_WATCHDOG,
52
+ asm("mov %0,#1; adr x16, 1f; br x16; 1: hint #25; mov %0,#0" \
269
+ .parent = TYPE_CMSDK_APB_WATCHDOG,
53
+ : "=r"(skipped) : : "x16", "x30")
270
+ .instance_init = luminary_watchdog_init
271
+};
272
+
54
+
273
static void cmsdk_apb_watchdog_register_types(void)
55
+#define BTYPE_2() \
274
{
56
+ asm("mov %0,#1; adr x16, 1f; blr x16; 1: hint #25; mov %0,#0" \
275
type_register_static(&cmsdk_apb_watchdog_info);
57
+ : "=r"(skipped) : : "x16", "x30")
276
+ type_register_static(&luminary_watchdog_info);
58
+
277
}
59
+#define BTYPE_3() \
278
60
+ asm("mov %0,#1; adr x15, 1f; br x15; 1: hint #25; mov %0,#0" \
279
type_init(cmsdk_apb_watchdog_register_types);
61
+ : "=r"(skipped) : : "x15", "x30")
62
+
63
+#define TEST(WHICH, EXPECT) \
64
+ do { WHICH(); fail += skipped ^ EXPECT; } while (0)
65
+
66
+int main()
67
+{
68
+ int fail = 0;
69
+ int skipped;
70
+
71
+ /* Signal-like with SA_SIGINFO. */
72
+ signal_info(SIGILL, skip2_sigill);
73
+
74
+ /* With SCTLR_EL1.BT0 set, PACIASP is not compatible with type=3. */
75
+ TEST(BTYPE_1, 0);
76
+ TEST(BTYPE_2, 0);
77
+ TEST(BTYPE_3, 1);
78
+
79
+ return fail;
80
+}
81
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
82
index XXXXXXX..XXXXXXX 100644
83
--- a/tests/tcg/aarch64/Makefile.target
84
+++ b/tests/tcg/aarch64/Makefile.target
85
@@ -XXX,XX +XXX,XX @@ endif
86
# BTI Tests
87
# bti-1 tests the elf notes, so we require special compiler support.
88
ifneq ($(CROSS_CC_HAS_ARMV8_BTI),)
89
-AARCH64_TESTS += bti-1
90
-bti-1: CFLAGS += -mbranch-protection=standard
91
-bti-1: LDFLAGS += -nostdlib
92
+AARCH64_TESTS += bti-1 bti-3
93
+bti-1 bti-3: CFLAGS += -mbranch-protection=standard
94
+bti-1 bti-3: LDFLAGS += -nostdlib
95
endif
96
# bti-2 tests PROT_BTI, so no special compiler support required.
97
AARCH64_TESTS += bti-2
280
--
98
--
281
2.20.1
99
2.25.1
282
283
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Move ARMCPRegInfo and all related declarations to a new
4
internal header, out of the public cpu.h.
5
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20190301200501.16533-3-richard.henderson@linaro.org
9
Message-id: 20220501055028.646596-2-richard.henderson@linaro.org
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
11
---
8
target/arm/cpu.h | 10 ++++++++++
12
target/arm/cpregs.h | 413 +++++++++++++++++++++++++++++++++++++
9
linux-user/elfload.c | 1 +
13
target/arm/cpu.h | 368 ---------------------------------
10
target/arm/cpu.c | 1 +
14
hw/arm/pxa2xx.c | 1 +
11
target/arm/cpu64.c | 2 ++
15
hw/arm/pxa2xx_pic.c | 1 +
12
target/arm/translate-a64.c | 14 ++++++++++++++
16
hw/intc/arm_gicv3_cpuif.c | 1 +
13
target/arm/translate.c | 22 ++++++++++++++++++++++
17
hw/intc/arm_gicv3_kvm.c | 2 +
14
6 files changed, 50 insertions(+)
18
target/arm/cpu.c | 1 +
19
target/arm/cpu64.c | 1 +
20
target/arm/cpu_tcg.c | 1 +
21
target/arm/gdbstub.c | 3 +-
22
target/arm/helper.c | 1 +
23
target/arm/op_helper.c | 1 +
24
target/arm/translate-a64.c | 4 +-
25
target/arm/translate.c | 3 +-
26
14 files changed, 427 insertions(+), 374 deletions(-)
27
create mode 100644 target/arm/cpregs.h
15
28
29
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
30
new file mode 100644
31
index XXXXXXX..XXXXXXX
32
--- /dev/null
33
+++ b/target/arm/cpregs.h
34
@@ -XXX,XX +XXX,XX @@
35
+/*
36
+ * QEMU ARM CP Register access and descriptions
37
+ *
38
+ * Copyright (c) 2022 Linaro Ltd
39
+ *
40
+ * This program is free software; you can redistribute it and/or
41
+ * modify it under the terms of the GNU General Public License
42
+ * as published by the Free Software Foundation; either version 2
43
+ * of the License, or (at your option) any later version.
44
+ *
45
+ * This program is distributed in the hope that it will be useful,
46
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
47
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48
+ * GNU General Public License for more details.
49
+ *
50
+ * You should have received a copy of the GNU General Public License
51
+ * along with this program; if not, see
52
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
53
+ */
54
+
55
+#ifndef TARGET_ARM_CPREGS_H
56
+#define TARGET_ARM_CPREGS_H
57
+
58
+/*
59
+ * ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
60
+ * special-behaviour cp reg and bits [11..8] indicate what behaviour
61
+ * it has. Otherwise it is a simple cp reg, where CONST indicates that
62
+ * TCG can assume the value to be constant (ie load at translate time)
63
+ * and 64BIT indicates a 64 bit wide coprocessor register. SUPPRESS_TB_END
64
+ * indicates that the TB should not be ended after a write to this register
65
+ * (the default is that the TB ends after cp writes). OVERRIDE permits
66
+ * a register definition to override a previous definition for the
67
+ * same (cp, is64, crn, crm, opc1, opc2) tuple: either the new or the
68
+ * old must have the OVERRIDE bit set.
69
+ * ALIAS indicates that this register is an alias view of some underlying
70
+ * state which is also visible via another register, and that the other
71
+ * register is handling migration and reset; registers marked ALIAS will not be
72
+ * migrated but may have their state set by syncing of register state from KVM.
73
+ * NO_RAW indicates that this register has no underlying state and does not
74
+ * support raw access for state saving/loading; it will not be used for either
75
+ * migration or KVM state synchronization. (Typically this is for "registers"
76
+ * which are actually used as instructions for cache maintenance and so on.)
77
+ * IO indicates that this register does I/O and therefore its accesses
78
+ * need to be marked with gen_io_start() and also end the TB. In particular,
79
+ * registers which implement clocks or timers require this.
80
+ * RAISES_EXC is for when the read or write hook might raise an exception;
81
+ * the generated code will synchronize the CPU state before calling the hook
82
+ * so that it is safe for the hook to call raise_exception().
83
+ * NEWEL is for writes to registers that might change the exception
84
+ * level - typically on older ARM chips. For those cases we need to
85
+ * re-read the new el when recomputing the translation flags.
86
+ */
87
+#define ARM_CP_SPECIAL 0x0001
88
+#define ARM_CP_CONST 0x0002
89
+#define ARM_CP_64BIT 0x0004
90
+#define ARM_CP_SUPPRESS_TB_END 0x0008
91
+#define ARM_CP_OVERRIDE 0x0010
92
+#define ARM_CP_ALIAS 0x0020
93
+#define ARM_CP_IO 0x0040
94
+#define ARM_CP_NO_RAW 0x0080
95
+#define ARM_CP_NOP (ARM_CP_SPECIAL | 0x0100)
96
+#define ARM_CP_WFI (ARM_CP_SPECIAL | 0x0200)
97
+#define ARM_CP_NZCV (ARM_CP_SPECIAL | 0x0300)
98
+#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400)
99
+#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | 0x0500)
100
+#define ARM_CP_DC_GVA (ARM_CP_SPECIAL | 0x0600)
101
+#define ARM_CP_DC_GZVA (ARM_CP_SPECIAL | 0x0700)
102
+#define ARM_LAST_SPECIAL ARM_CP_DC_GZVA
103
+#define ARM_CP_FPU 0x1000
104
+#define ARM_CP_SVE 0x2000
105
+#define ARM_CP_NO_GDB 0x4000
106
+#define ARM_CP_RAISES_EXC 0x8000
107
+#define ARM_CP_NEWEL 0x10000
108
+/* Used only as a terminator for ARMCPRegInfo lists */
109
+#define ARM_CP_SENTINEL 0xfffff
110
+/* Mask of only the flag bits in a type field */
111
+#define ARM_CP_FLAG_MASK 0x1f0ff
112
+
113
+/*
114
+ * Valid values for ARMCPRegInfo state field, indicating which of
115
+ * the AArch32 and AArch64 execution states this register is visible in.
116
+ * If the reginfo doesn't explicitly specify then it is AArch32 only.
117
+ * If the reginfo is declared to be visible in both states then a second
118
+ * reginfo is synthesised for the AArch32 view of the AArch64 register,
119
+ * such that the AArch32 view is the lower 32 bits of the AArch64 one.
120
+ * Note that we rely on the values of these enums as we iterate through
121
+ * the various states in some places.
122
+ */
123
+enum {
124
+ ARM_CP_STATE_AA32 = 0,
125
+ ARM_CP_STATE_AA64 = 1,
126
+ ARM_CP_STATE_BOTH = 2,
127
+};
128
+
129
+/*
130
+ * ARM CP register secure state flags. These flags identify security state
131
+ * attributes for a given CP register entry.
132
+ * The existence of both or neither secure and non-secure flags indicates that
133
+ * the register has both a secure and non-secure hash entry. A single one of
134
+ * these flags causes the register to only be hashed for the specified
135
+ * security state.
136
+ * Although definitions may have any combination of the S/NS bits, each
137
+ * registered entry will only have one to identify whether the entry is secure
138
+ * or non-secure.
139
+ */
140
+enum {
141
+ ARM_CP_SECSTATE_S = (1 << 0), /* bit[0]: Secure state register */
142
+ ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
143
+};
144
+
145
+/*
146
+ * Return true if cptype is a valid type field. This is used to try to
147
+ * catch errors where the sentinel has been accidentally left off the end
148
+ * of a list of registers.
149
+ */
150
+static inline bool cptype_valid(int cptype)
151
+{
152
+ return ((cptype & ~ARM_CP_FLAG_MASK) == 0)
153
+ || ((cptype & ARM_CP_SPECIAL) &&
154
+ ((cptype & ~ARM_CP_FLAG_MASK) <= ARM_LAST_SPECIAL));
155
+}
156
+
157
+/*
158
+ * Access rights:
159
+ * We define bits for Read and Write access for what rev C of the v7-AR ARM ARM
160
+ * defines as PL0 (user), PL1 (fiq/irq/svc/abt/und/sys, ie privileged), and
161
+ * PL2 (hyp). The other level which has Read and Write bits is Secure PL1
162
+ * (ie any of the privileged modes in Secure state, or Monitor mode).
163
+ * If a register is accessible in one privilege level it's always accessible
164
+ * in higher privilege levels too. Since "Secure PL1" also follows this rule
165
+ * (ie anything visible in PL2 is visible in S-PL1, some things are only
166
+ * visible in S-PL1) but "Secure PL1" is a bit of a mouthful, we bend the
167
+ * terminology a little and call this PL3.
168
+ * In AArch64 things are somewhat simpler as the PLx bits line up exactly
169
+ * with the ELx exception levels.
170
+ *
171
+ * If access permissions for a register are more complex than can be
172
+ * described with these bits, then use a laxer set of restrictions, and
173
+ * do the more restrictive/complex check inside a helper function.
174
+ */
175
+#define PL3_R 0x80
176
+#define PL3_W 0x40
177
+#define PL2_R (0x20 | PL3_R)
178
+#define PL2_W (0x10 | PL3_W)
179
+#define PL1_R (0x08 | PL2_R)
180
+#define PL1_W (0x04 | PL2_W)
181
+#define PL0_R (0x02 | PL1_R)
182
+#define PL0_W (0x01 | PL1_W)
183
+
184
+/*
185
+ * For user-mode some registers are accessible to EL0 via a kernel
186
+ * trap-and-emulate ABI. In this case we define the read permissions
187
+ * as actually being PL0_R. However some bits of any given register
188
+ * may still be masked.
189
+ */
190
+#ifdef CONFIG_USER_ONLY
191
+#define PL0U_R PL0_R
192
+#else
193
+#define PL0U_R PL1_R
194
+#endif
195
+
196
+#define PL3_RW (PL3_R | PL3_W)
197
+#define PL2_RW (PL2_R | PL2_W)
198
+#define PL1_RW (PL1_R | PL1_W)
199
+#define PL0_RW (PL0_R | PL0_W)
200
+
201
+typedef enum CPAccessResult {
202
+ /* Access is permitted */
203
+ CP_ACCESS_OK = 0,
204
+ /*
205
+ * Access fails due to a configurable trap or enable which would
206
+ * result in a categorized exception syndrome giving information about
207
+ * the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6,
208
+ * 0xc or 0x18). The exception is taken to the usual target EL (EL1 or
209
+ * PL1 if in EL0, otherwise to the current EL).
210
+ */
211
+ CP_ACCESS_TRAP = 1,
212
+ /*
213
+ * Access fails and results in an exception syndrome 0x0 ("uncategorized").
214
+ * Note that this is not a catch-all case -- the set of cases which may
215
+ * result in this failure is specifically defined by the architecture.
216
+ */
217
+ CP_ACCESS_TRAP_UNCATEGORIZED = 2,
218
+ /* As CP_ACCESS_TRAP, but for traps directly to EL2 or EL3 */
219
+ CP_ACCESS_TRAP_EL2 = 3,
220
+ CP_ACCESS_TRAP_EL3 = 4,
221
+ /* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */
222
+ CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5,
223
+ CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6,
224
+} CPAccessResult;
225
+
226
+typedef struct ARMCPRegInfo ARMCPRegInfo;
227
+
228
+/*
229
+ * Access functions for coprocessor registers. These cannot fail and
230
+ * may not raise exceptions.
231
+ */
232
+typedef uint64_t CPReadFn(CPUARMState *env, const ARMCPRegInfo *opaque);
233
+typedef void CPWriteFn(CPUARMState *env, const ARMCPRegInfo *opaque,
234
+ uint64_t value);
235
+/* Access permission check functions for coprocessor registers. */
236
+typedef CPAccessResult CPAccessFn(CPUARMState *env,
237
+ const ARMCPRegInfo *opaque,
238
+ bool isread);
239
+/* Hook function for register reset */
240
+typedef void CPResetFn(CPUARMState *env, const ARMCPRegInfo *opaque);
241
+
242
+#define CP_ANY 0xff
243
+
244
+/* Definition of an ARM coprocessor register */
245
+struct ARMCPRegInfo {
246
+ /* Name of register (useful mainly for debugging, need not be unique) */
247
+ const char *name;
248
+ /*
249
+ * Location of register: coprocessor number and (crn,crm,opc1,opc2)
250
+ * tuple. Any of crm, opc1 and opc2 may be CP_ANY to indicate a
251
+ * 'wildcard' field -- any value of that field in the MRC/MCR insn
252
+ * will be decoded to this register. The register read and write
253
+ * callbacks will be passed an ARMCPRegInfo with the crn/crm/opc1/opc2
254
+ * used by the program, so it is possible to register a wildcard and
255
+ * then behave differently on read/write if necessary.
256
+ * For 64 bit registers, only crm and opc1 are relevant; crn and opc2
257
+ * must both be zero.
258
+ * For AArch64-visible registers, opc0 is also used.
259
+ * Since there are no "coprocessors" in AArch64, cp is purely used as a
260
+ * way to distinguish (for KVM's benefit) guest-visible system registers
261
+ * from demuxed ones provided to preserve the "no side effects on
262
+ * KVM register read/write from QEMU" semantics. cp==0x13 is guest
263
+ * visible (to match KVM's encoding); cp==0 will be converted to
264
+ * cp==0x13 when the ARMCPRegInfo is registered, for convenience.
265
+ */
266
+ uint8_t cp;
267
+ uint8_t crn;
268
+ uint8_t crm;
269
+ uint8_t opc0;
270
+ uint8_t opc1;
271
+ uint8_t opc2;
272
+ /* Execution state in which this register is visible: ARM_CP_STATE_* */
273
+ int state;
274
+ /* Register type: ARM_CP_* bits/values */
275
+ int type;
276
+ /* Access rights: PL*_[RW] */
277
+ int access;
278
+ /* Security state: ARM_CP_SECSTATE_* bits/values */
279
+ int secure;
280
+ /*
281
+ * The opaque pointer passed to define_arm_cp_regs_with_opaque() when
282
+ * this register was defined: can be used to hand data through to the
283
+ * register read/write functions, since they are passed the ARMCPRegInfo*.
284
+ */
285
+ void *opaque;
286
+ /*
287
+ * Value of this register, if it is ARM_CP_CONST. Otherwise, if
288
+ * fieldoffset is non-zero, the reset value of the register.
289
+ */
290
+ uint64_t resetvalue;
291
+ /*
292
+ * Offset of the field in CPUARMState for this register.
293
+ * This is not needed if either:
294
+ * 1. type is ARM_CP_CONST or one of the ARM_CP_SPECIALs
295
+ * 2. both readfn and writefn are specified
296
+ */
297
+ ptrdiff_t fieldoffset; /* offsetof(CPUARMState, field) */
298
+
299
+ /*
300
+ * Offsets of the secure and non-secure fields in CPUARMState for the
301
+ * register if it is banked. These fields are only used during the static
302
+ * registration of a register. During hashing the bank associated
303
+ * with a given security state is copied to fieldoffset which is used from
304
+ * there on out.
305
+ *
306
+ * It is expected that register definitions use either fieldoffset or
307
+ * bank_fieldoffsets in the definition but not both. It is also expected
308
+ * that both bank offsets are set when defining a banked register. This
309
+ * use indicates that a register is banked.
310
+ */
311
+ ptrdiff_t bank_fieldoffsets[2];
312
+
313
+ /*
314
+ * Function for making any access checks for this register in addition to
315
+ * those specified by the 'access' permissions bits. If NULL, no extra
316
+ * checks required. The access check is performed at runtime, not at
317
+ * translate time.
318
+ */
319
+ CPAccessFn *accessfn;
320
+ /*
321
+ * Function for handling reads of this register. If NULL, then reads
322
+ * will be done by loading from the offset into CPUARMState specified
323
+ * by fieldoffset.
324
+ */
325
+ CPReadFn *readfn;
326
+ /*
327
+ * Function for handling writes of this register. If NULL, then writes
328
+ * will be done by writing to the offset into CPUARMState specified
329
+ * by fieldoffset.
330
+ */
331
+ CPWriteFn *writefn;
332
+ /*
333
+ * Function for doing a "raw" read; used when we need to copy
334
+ * coprocessor state to the kernel for KVM or out for
335
+ * migration. This only needs to be provided if there is also a
336
+ * readfn and it has side effects (for instance clear-on-read bits).
337
+ */
338
+ CPReadFn *raw_readfn;
339
+ /*
340
+ * Function for doing a "raw" write; used when we need to copy KVM
341
+ * kernel coprocessor state into userspace, or for inbound
342
+ * migration. This only needs to be provided if there is also a
343
+ * writefn and it masks out "unwritable" bits or has write-one-to-clear
344
+ * or similar behaviour.
345
+ */
346
+ CPWriteFn *raw_writefn;
347
+ /*
348
+ * Function for resetting the register. If NULL, then reset will be done
349
+ * by writing resetvalue to the field specified in fieldoffset. If
350
+ * fieldoffset is 0 then no reset will be done.
351
+ */
352
+ CPResetFn *resetfn;
353
+
354
+ /*
355
+ * "Original" writefn and readfn.
356
+ * For ARMv8.1-VHE register aliases, we overwrite the read/write
357
+ * accessor functions of various EL1/EL0 to perform the runtime
358
+ * check for which sysreg should actually be modified, and then
359
+ * forwards the operation. Before overwriting the accessors,
360
+ * the original function is copied here, so that accesses that
361
+ * really do go to the EL1/EL0 version proceed normally.
362
+ * (The corresponding EL2 register is linked via opaque.)
363
+ */
364
+ CPReadFn *orig_readfn;
365
+ CPWriteFn *orig_writefn;
366
+};
367
+
368
+/*
369
+ * Macros which are lvalues for the field in CPUARMState for the
370
+ * ARMCPRegInfo *ri.
371
+ */
372
+#define CPREG_FIELD32(env, ri) \
373
+ (*(uint32_t *)((char *)(env) + (ri)->fieldoffset))
374
+#define CPREG_FIELD64(env, ri) \
375
+ (*(uint64_t *)((char *)(env) + (ri)->fieldoffset))
376
+
377
+#define REGINFO_SENTINEL { .type = ARM_CP_SENTINEL }
378
+
379
+void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
380
+ const ARMCPRegInfo *regs, void *opaque);
381
+void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
382
+ const ARMCPRegInfo *regs, void *opaque);
383
+static inline void define_arm_cp_regs(ARMCPU *cpu, const ARMCPRegInfo *regs)
384
+{
385
+ define_arm_cp_regs_with_opaque(cpu, regs, 0);
386
+}
387
+static inline void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *regs)
388
+{
389
+ define_one_arm_cp_reg_with_opaque(cpu, regs, 0);
390
+}
391
+const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp);
392
+
393
+/*
394
+ * Definition of an ARM co-processor register as viewed from
395
+ * userspace. This is used for presenting sanitised versions of
396
+ * registers to userspace when emulating the Linux AArch64 CPU
397
+ * ID/feature ABI (advertised as HWCAP_CPUID).
398
+ */
399
+typedef struct ARMCPRegUserSpaceInfo {
400
+ /* Name of register */
401
+ const char *name;
402
+
403
+ /* Is the name actually a glob pattern */
404
+ bool is_glob;
405
+
406
+ /* Only some bits are exported to user space */
407
+ uint64_t exported_bits;
408
+
409
+ /* Fixed bits are applied after the mask */
410
+ uint64_t fixed_bits;
411
+} ARMCPRegUserSpaceInfo;
412
+
413
+#define REGUSERINFO_SENTINEL { .name = NULL }
414
+
415
+void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods);
416
+
417
+/* CPWriteFn that can be used to implement writes-ignored behaviour */
418
+void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
419
+ uint64_t value);
420
+/* CPReadFn that can be used for read-as-zero behaviour */
421
+uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri);
422
+
423
+/*
424
+ * CPResetFn that does nothing, for use if no reset is required even
425
+ * if fieldoffset is non zero.
426
+ */
427
+void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque);
428
+
429
+/*
430
+ * Return true if this reginfo struct's field in the cpu state struct
431
+ * is 64 bits wide.
432
+ */
433
+static inline bool cpreg_field_is_64bit(const ARMCPRegInfo *ri)
434
+{
435
+ return (ri->state == ARM_CP_STATE_AA64) || (ri->type & ARM_CP_64BIT);
436
+}
437
+
438
+static inline bool cp_access_ok(int current_el,
439
+ const ARMCPRegInfo *ri, int isread)
440
+{
441
+ return (ri->access >> ((current_el * 2) + isread)) & 1;
442
+}
443
+
444
+/* Raw read of a coprocessor register (as needed for migration, etc) */
445
+uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri);
446
+
447
+#endif /* TARGET_ARM_CPREGS_H */
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
448
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
449
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
450
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
451
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fhm(const ARMISARegisters *id)
452
@@ -XXX,XX +XXX,XX @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
21
return FIELD_EX32(id->id_isar6, ID_ISAR6, FHM) != 0;
453
return kvmid;
22
}
454
}
23
455
24
+static inline bool isar_feature_aa32_sb(const ARMISARegisters *id)
456
-/* ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
25
+{
457
- * special-behaviour cp reg and bits [11..8] indicate what behaviour
26
+ return FIELD_EX32(id->id_isar6, ID_ISAR6, SB) != 0;
458
- * it has. Otherwise it is a simple cp reg, where CONST indicates that
27
+}
459
- * TCG can assume the value to be constant (ie load at translate time)
28
+
460
- * and 64BIT indicates a 64 bit wide coprocessor register. SUPPRESS_TB_END
29
static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
461
- * indicates that the TB should not be ended after a write to this register
462
- * (the default is that the TB ends after cp writes). OVERRIDE permits
463
- * a register definition to override a previous definition for the
464
- * same (cp, is64, crn, crm, opc1, opc2) tuple: either the new or the
465
- * old must have the OVERRIDE bit set.
466
- * ALIAS indicates that this register is an alias view of some underlying
467
- * state which is also visible via another register, and that the other
468
- * register is handling migration and reset; registers marked ALIAS will not be
469
- * migrated but may have their state set by syncing of register state from KVM.
470
- * NO_RAW indicates that this register has no underlying state and does not
471
- * support raw access for state saving/loading; it will not be used for either
472
- * migration or KVM state synchronization. (Typically this is for "registers"
473
- * which are actually used as instructions for cache maintenance and so on.)
474
- * IO indicates that this register does I/O and therefore its accesses
475
- * need to be marked with gen_io_start() and also end the TB. In particular,
476
- * registers which implement clocks or timers require this.
477
- * RAISES_EXC is for when the read or write hook might raise an exception;
478
- * the generated code will synchronize the CPU state before calling the hook
479
- * so that it is safe for the hook to call raise_exception().
480
- * NEWEL is for writes to registers that might change the exception
481
- * level - typically on older ARM chips. For those cases we need to
482
- * re-read the new el when recomputing the translation flags.
483
- */
484
-#define ARM_CP_SPECIAL 0x0001
485
-#define ARM_CP_CONST 0x0002
486
-#define ARM_CP_64BIT 0x0004
487
-#define ARM_CP_SUPPRESS_TB_END 0x0008
488
-#define ARM_CP_OVERRIDE 0x0010
489
-#define ARM_CP_ALIAS 0x0020
490
-#define ARM_CP_IO 0x0040
491
-#define ARM_CP_NO_RAW 0x0080
492
-#define ARM_CP_NOP (ARM_CP_SPECIAL | 0x0100)
493
-#define ARM_CP_WFI (ARM_CP_SPECIAL | 0x0200)
494
-#define ARM_CP_NZCV (ARM_CP_SPECIAL | 0x0300)
495
-#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400)
496
-#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | 0x0500)
497
-#define ARM_CP_DC_GVA (ARM_CP_SPECIAL | 0x0600)
498
-#define ARM_CP_DC_GZVA (ARM_CP_SPECIAL | 0x0700)
499
-#define ARM_LAST_SPECIAL ARM_CP_DC_GZVA
500
-#define ARM_CP_FPU 0x1000
501
-#define ARM_CP_SVE 0x2000
502
-#define ARM_CP_NO_GDB 0x4000
503
-#define ARM_CP_RAISES_EXC 0x8000
504
-#define ARM_CP_NEWEL 0x10000
505
-/* Used only as a terminator for ARMCPRegInfo lists */
506
-#define ARM_CP_SENTINEL 0xfffff
507
-/* Mask of only the flag bits in a type field */
508
-#define ARM_CP_FLAG_MASK 0x1f0ff
509
-
510
-/* Valid values for ARMCPRegInfo state field, indicating which of
511
- * the AArch32 and AArch64 execution states this register is visible in.
512
- * If the reginfo doesn't explicitly specify then it is AArch32 only.
513
- * If the reginfo is declared to be visible in both states then a second
514
- * reginfo is synthesised for the AArch32 view of the AArch64 register,
515
- * such that the AArch32 view is the lower 32 bits of the AArch64 one.
516
- * Note that we rely on the values of these enums as we iterate through
517
- * the various states in some places.
518
- */
519
-enum {
520
- ARM_CP_STATE_AA32 = 0,
521
- ARM_CP_STATE_AA64 = 1,
522
- ARM_CP_STATE_BOTH = 2,
523
-};
524
-
525
-/* ARM CP register secure state flags. These flags identify security state
526
- * attributes for a given CP register entry.
527
- * The existence of both or neither secure and non-secure flags indicates that
528
- * the register has both a secure and non-secure hash entry. A single one of
529
- * these flags causes the register to only be hashed for the specified
530
- * security state.
531
- * Although definitions may have any combination of the S/NS bits, each
532
- * registered entry will only have one to identify whether the entry is secure
533
- * or non-secure.
534
- */
535
-enum {
536
- ARM_CP_SECSTATE_S = (1 << 0), /* bit[0]: Secure state register */
537
- ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
538
-};
539
-
540
-/* Return true if cptype is a valid type field. This is used to try to
541
- * catch errors where the sentinel has been accidentally left off the end
542
- * of a list of registers.
543
- */
544
-static inline bool cptype_valid(int cptype)
545
-{
546
- return ((cptype & ~ARM_CP_FLAG_MASK) == 0)
547
- || ((cptype & ARM_CP_SPECIAL) &&
548
- ((cptype & ~ARM_CP_FLAG_MASK) <= ARM_LAST_SPECIAL));
549
-}
550
-
551
-/* Access rights:
552
- * We define bits for Read and Write access for what rev C of the v7-AR ARM ARM
553
- * defines as PL0 (user), PL1 (fiq/irq/svc/abt/und/sys, ie privileged), and
554
- * PL2 (hyp). The other level which has Read and Write bits is Secure PL1
555
- * (ie any of the privileged modes in Secure state, or Monitor mode).
556
- * If a register is accessible in one privilege level it's always accessible
557
- * in higher privilege levels too. Since "Secure PL1" also follows this rule
558
- * (ie anything visible in PL2 is visible in S-PL1, some things are only
559
- * visible in S-PL1) but "Secure PL1" is a bit of a mouthful, we bend the
560
- * terminology a little and call this PL3.
561
- * In AArch64 things are somewhat simpler as the PLx bits line up exactly
562
- * with the ELx exception levels.
563
- *
564
- * If access permissions for a register are more complex than can be
565
- * described with these bits, then use a laxer set of restrictions, and
566
- * do the more restrictive/complex check inside a helper function.
567
- */
568
-#define PL3_R 0x80
569
-#define PL3_W 0x40
570
-#define PL2_R (0x20 | PL3_R)
571
-#define PL2_W (0x10 | PL3_W)
572
-#define PL1_R (0x08 | PL2_R)
573
-#define PL1_W (0x04 | PL2_W)
574
-#define PL0_R (0x02 | PL1_R)
575
-#define PL0_W (0x01 | PL1_W)
576
-
577
-/*
578
- * For user-mode some registers are accessible to EL0 via a kernel
579
- * trap-and-emulate ABI. In this case we define the read permissions
580
- * as actually being PL0_R. However some bits of any given register
581
- * may still be masked.
582
- */
583
-#ifdef CONFIG_USER_ONLY
584
-#define PL0U_R PL0_R
585
-#else
586
-#define PL0U_R PL1_R
587
-#endif
588
-
589
-#define PL3_RW (PL3_R | PL3_W)
590
-#define PL2_RW (PL2_R | PL2_W)
591
-#define PL1_RW (PL1_R | PL1_W)
592
-#define PL0_RW (PL0_R | PL0_W)
593
-
594
/* Return the highest implemented Exception Level */
595
static inline int arm_highest_el(CPUARMState *env)
30
{
596
{
31
/*
597
@@ -XXX,XX +XXX,XX @@ static inline int arm_current_el(CPUARMState *env)
32
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id)
598
}
33
FIELD_DP64(0, ID_AA64ISAR1, GPI, 0xf))) != 0;
34
}
599
}
35
600
36
+static inline bool isar_feature_aa64_sb(const ARMISARegisters *id)
601
-typedef struct ARMCPRegInfo ARMCPRegInfo;
37
+{
602
-
38
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SB) != 0;
603
-typedef enum CPAccessResult {
39
+}
604
- /* Access is permitted */
40
+
605
- CP_ACCESS_OK = 0,
41
static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
606
- /* Access fails due to a configurable trap or enable which would
42
{
607
- * result in a categorized exception syndrome giving information about
43
/* We always set the AdvSIMD and FP fields identically wrt FP16. */
608
- * the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6,
44
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
609
- * 0xc or 0x18). The exception is taken to the usual target EL (EL1 or
45
index XXXXXXX..XXXXXXX 100644
610
- * PL1 if in EL0, otherwise to the current EL).
46
--- a/linux-user/elfload.c
611
- */
47
+++ b/linux-user/elfload.c
612
- CP_ACCESS_TRAP = 1,
48
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
613
- /* Access fails and results in an exception syndrome 0x0 ("uncategorized").
49
GET_FEATURE_ID(aa64_pauth, ARM_HWCAP_A64_PACA | ARM_HWCAP_A64_PACG);
614
- * Note that this is not a catch-all case -- the set of cases which may
50
GET_FEATURE_ID(aa64_fhm, ARM_HWCAP_A64_ASIMDFHM);
615
- * result in this failure is specifically defined by the architecture.
51
GET_FEATURE_ID(aa64_jscvt, ARM_HWCAP_A64_JSCVT);
616
- */
52
+ GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB);
617
- CP_ACCESS_TRAP_UNCATEGORIZED = 2,
53
618
- /* As CP_ACCESS_TRAP, but for traps directly to EL2 or EL3 */
54
#undef GET_FEATURE_ID
619
- CP_ACCESS_TRAP_EL2 = 3,
55
620
- CP_ACCESS_TRAP_EL3 = 4,
621
- /* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */
622
- CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5,
623
- CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6,
624
-} CPAccessResult;
625
-
626
-/* Access functions for coprocessor registers. These cannot fail and
627
- * may not raise exceptions.
628
- */
629
-typedef uint64_t CPReadFn(CPUARMState *env, const ARMCPRegInfo *opaque);
630
-typedef void CPWriteFn(CPUARMState *env, const ARMCPRegInfo *opaque,
631
- uint64_t value);
632
-/* Access permission check functions for coprocessor registers. */
633
-typedef CPAccessResult CPAccessFn(CPUARMState *env,
634
- const ARMCPRegInfo *opaque,
635
- bool isread);
636
-/* Hook function for register reset */
637
-typedef void CPResetFn(CPUARMState *env, const ARMCPRegInfo *opaque);
638
-
639
-#define CP_ANY 0xff
640
-
641
-/* Definition of an ARM coprocessor register */
642
-struct ARMCPRegInfo {
643
- /* Name of register (useful mainly for debugging, need not be unique) */
644
- const char *name;
645
- /* Location of register: coprocessor number and (crn,crm,opc1,opc2)
646
- * tuple. Any of crm, opc1 and opc2 may be CP_ANY to indicate a
647
- * 'wildcard' field -- any value of that field in the MRC/MCR insn
648
- * will be decoded to this register. The register read and write
649
- * callbacks will be passed an ARMCPRegInfo with the crn/crm/opc1/opc2
650
- * used by the program, so it is possible to register a wildcard and
651
- * then behave differently on read/write if necessary.
652
- * For 64 bit registers, only crm and opc1 are relevant; crn and opc2
653
- * must both be zero.
654
- * For AArch64-visible registers, opc0 is also used.
655
- * Since there are no "coprocessors" in AArch64, cp is purely used as a
656
- * way to distinguish (for KVM's benefit) guest-visible system registers
657
- * from demuxed ones provided to preserve the "no side effects on
658
- * KVM register read/write from QEMU" semantics. cp==0x13 is guest
659
- * visible (to match KVM's encoding); cp==0 will be converted to
660
- * cp==0x13 when the ARMCPRegInfo is registered, for convenience.
661
- */
662
- uint8_t cp;
663
- uint8_t crn;
664
- uint8_t crm;
665
- uint8_t opc0;
666
- uint8_t opc1;
667
- uint8_t opc2;
668
- /* Execution state in which this register is visible: ARM_CP_STATE_* */
669
- int state;
670
- /* Register type: ARM_CP_* bits/values */
671
- int type;
672
- /* Access rights: PL*_[RW] */
673
- int access;
674
- /* Security state: ARM_CP_SECSTATE_* bits/values */
675
- int secure;
676
- /* The opaque pointer passed to define_arm_cp_regs_with_opaque() when
677
- * this register was defined: can be used to hand data through to the
678
- * register read/write functions, since they are passed the ARMCPRegInfo*.
679
- */
680
- void *opaque;
681
- /* Value of this register, if it is ARM_CP_CONST. Otherwise, if
682
- * fieldoffset is non-zero, the reset value of the register.
683
- */
684
- uint64_t resetvalue;
685
- /* Offset of the field in CPUARMState for this register.
686
- *
687
- * This is not needed if either:
688
- * 1. type is ARM_CP_CONST or one of the ARM_CP_SPECIALs
689
- * 2. both readfn and writefn are specified
690
- */
691
- ptrdiff_t fieldoffset; /* offsetof(CPUARMState, field) */
692
-
693
- /* Offsets of the secure and non-secure fields in CPUARMState for the
694
- * register if it is banked. These fields are only used during the static
695
- * registration of a register. During hashing the bank associated
696
- * with a given security state is copied to fieldoffset which is used from
697
- * there on out.
698
- *
699
- * It is expected that register definitions use either fieldoffset or
700
- * bank_fieldoffsets in the definition but not both. It is also expected
701
- * that both bank offsets are set when defining a banked register. This
702
- * use indicates that a register is banked.
703
- */
704
- ptrdiff_t bank_fieldoffsets[2];
705
-
706
- /* Function for making any access checks for this register in addition to
707
- * those specified by the 'access' permissions bits. If NULL, no extra
708
- * checks required. The access check is performed at runtime, not at
709
- * translate time.
710
- */
711
- CPAccessFn *accessfn;
712
- /* Function for handling reads of this register. If NULL, then reads
713
- * will be done by loading from the offset into CPUARMState specified
714
- * by fieldoffset.
715
- */
716
- CPReadFn *readfn;
717
- /* Function for handling writes of this register. If NULL, then writes
718
- * will be done by writing to the offset into CPUARMState specified
719
- * by fieldoffset.
720
- */
721
- CPWriteFn *writefn;
722
- /* Function for doing a "raw" read; used when we need to copy
723
- * coprocessor state to the kernel for KVM or out for
724
- * migration. This only needs to be provided if there is also a
725
- * readfn and it has side effects (for instance clear-on-read bits).
726
- */
727
- CPReadFn *raw_readfn;
728
- /* Function for doing a "raw" write; used when we need to copy KVM
729
- * kernel coprocessor state into userspace, or for inbound
730
- * migration. This only needs to be provided if there is also a
731
- * writefn and it masks out "unwritable" bits or has write-one-to-clear
732
- * or similar behaviour.
733
- */
734
- CPWriteFn *raw_writefn;
735
- /* Function for resetting the register. If NULL, then reset will be done
736
- * by writing resetvalue to the field specified in fieldoffset. If
737
- * fieldoffset is 0 then no reset will be done.
738
- */
739
- CPResetFn *resetfn;
740
-
741
- /*
742
- * "Original" writefn and readfn.
743
- * For ARMv8.1-VHE register aliases, we overwrite the read/write
744
- * accessor functions of various EL1/EL0 to perform the runtime
745
- * check for which sysreg should actually be modified, and then
746
- * forwards the operation. Before overwriting the accessors,
747
- * the original function is copied here, so that accesses that
748
- * really do go to the EL1/EL0 version proceed normally.
749
- * (The corresponding EL2 register is linked via opaque.)
750
- */
751
- CPReadFn *orig_readfn;
752
- CPWriteFn *orig_writefn;
753
-};
754
-
755
-/* Macros which are lvalues for the field in CPUARMState for the
756
- * ARMCPRegInfo *ri.
757
- */
758
-#define CPREG_FIELD32(env, ri) \
759
- (*(uint32_t *)((char *)(env) + (ri)->fieldoffset))
760
-#define CPREG_FIELD64(env, ri) \
761
- (*(uint64_t *)((char *)(env) + (ri)->fieldoffset))
762
-
763
-#define REGINFO_SENTINEL { .type = ARM_CP_SENTINEL }
764
-
765
-void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
766
- const ARMCPRegInfo *regs, void *opaque);
767
-void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
768
- const ARMCPRegInfo *regs, void *opaque);
769
-static inline void define_arm_cp_regs(ARMCPU *cpu, const ARMCPRegInfo *regs)
770
-{
771
- define_arm_cp_regs_with_opaque(cpu, regs, 0);
772
-}
773
-static inline void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *regs)
774
-{
775
- define_one_arm_cp_reg_with_opaque(cpu, regs, 0);
776
-}
777
-const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp);
778
-
779
-/*
780
- * Definition of an ARM co-processor register as viewed from
781
- * userspace. This is used for presenting sanitised versions of
782
- * registers to userspace when emulating the Linux AArch64 CPU
783
- * ID/feature ABI (advertised as HWCAP_CPUID).
784
- */
785
-typedef struct ARMCPRegUserSpaceInfo {
786
- /* Name of register */
787
- const char *name;
788
-
789
- /* Is the name actually a glob pattern */
790
- bool is_glob;
791
-
792
- /* Only some bits are exported to user space */
793
- uint64_t exported_bits;
794
-
795
- /* Fixed bits are applied after the mask */
796
- uint64_t fixed_bits;
797
-} ARMCPRegUserSpaceInfo;
798
-
799
-#define REGUSERINFO_SENTINEL { .name = NULL }
800
-
801
-void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods);
802
-
803
-/* CPWriteFn that can be used to implement writes-ignored behaviour */
804
-void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
805
- uint64_t value);
806
-/* CPReadFn that can be used for read-as-zero behaviour */
807
-uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri);
808
-
809
-/* CPResetFn that does nothing, for use if no reset is required even
810
- * if fieldoffset is non zero.
811
- */
812
-void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque);
813
-
814
-/* Return true if this reginfo struct's field in the cpu state struct
815
- * is 64 bits wide.
816
- */
817
-static inline bool cpreg_field_is_64bit(const ARMCPRegInfo *ri)
818
-{
819
- return (ri->state == ARM_CP_STATE_AA64) || (ri->type & ARM_CP_64BIT);
820
-}
821
-
822
-static inline bool cp_access_ok(int current_el,
823
- const ARMCPRegInfo *ri, int isread)
824
-{
825
- return (ri->access >> ((current_el * 2) + isread)) & 1;
826
-}
827
-
828
-/* Raw read of a coprocessor register (as needed for migration, etc) */
829
-uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri);
830
-
831
/**
832
* write_list_to_cpustate
833
* @cpu: ARMCPU
834
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
835
index XXXXXXX..XXXXXXX 100644
836
--- a/hw/arm/pxa2xx.c
837
+++ b/hw/arm/pxa2xx.c
838
@@ -XXX,XX +XXX,XX @@
839
#include "qemu/cutils.h"
840
#include "qemu/log.h"
841
#include "qom/object.h"
842
+#include "target/arm/cpregs.h"
843
844
static struct {
845
hwaddr io_base;
846
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
847
index XXXXXXX..XXXXXXX 100644
848
--- a/hw/arm/pxa2xx_pic.c
849
+++ b/hw/arm/pxa2xx_pic.c
850
@@ -XXX,XX +XXX,XX @@
851
#include "hw/sysbus.h"
852
#include "migration/vmstate.h"
853
#include "qom/object.h"
854
+#include "target/arm/cpregs.h"
855
856
#define ICIP    0x00    /* Interrupt Controller IRQ Pending register */
857
#define ICMR    0x04    /* Interrupt Controller Mask register */
858
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
859
index XXXXXXX..XXXXXXX 100644
860
--- a/hw/intc/arm_gicv3_cpuif.c
861
+++ b/hw/intc/arm_gicv3_cpuif.c
862
@@ -XXX,XX +XXX,XX @@
863
#include "gicv3_internal.h"
864
#include "hw/irq.h"
865
#include "cpu.h"
866
+#include "target/arm/cpregs.h"
867
868
/*
869
* Special case return value from hppvi_index(); must be larger than
870
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
871
index XXXXXXX..XXXXXXX 100644
872
--- a/hw/intc/arm_gicv3_kvm.c
873
+++ b/hw/intc/arm_gicv3_kvm.c
874
@@ -XXX,XX +XXX,XX @@
875
#include "vgic_common.h"
876
#include "migration/blocker.h"
877
#include "qom/object.h"
878
+#include "target/arm/cpregs.h"
879
+
880
881
#ifdef DEBUG_GICV3_KVM
882
#define DPRINTF(fmt, ...) \
56
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
883
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
57
index XXXXXXX..XXXXXXX 100644
884
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/cpu.c
885
--- a/target/arm/cpu.c
59
+++ b/target/arm/cpu.c
886
+++ b/target/arm/cpu.c
60
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
887
@@ -XXX,XX +XXX,XX @@
61
t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
888
#include "kvm_arm.h"
62
t = FIELD_DP32(t, ID_ISAR6, DP, 1);
889
#include "disas/capstone.h"
63
t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
890
#include "fpu/softfloat.h"
64
+ t = FIELD_DP32(t, ID_ISAR6, SB, 1);
891
+#include "cpregs.h"
65
cpu->isar.id_isar6 = t;
892
66
893
static void arm_cpu_set_pc(CPUState *cs, vaddr value)
67
t = cpu->id_mmfr4;
894
{
68
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
895
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
69
index XXXXXXX..XXXXXXX 100644
896
index XXXXXXX..XXXXXXX 100644
70
--- a/target/arm/cpu64.c
897
--- a/target/arm/cpu64.c
71
+++ b/target/arm/cpu64.c
898
+++ b/target/arm/cpu64.c
72
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
899
@@ -XXX,XX +XXX,XX @@
73
t = FIELD_DP64(t, ID_AA64ISAR1, API, 0);
900
#include "hvf_arm.h"
74
t = FIELD_DP64(t, ID_AA64ISAR1, GPA, 1);
901
#include "qapi/visitor.h"
75
t = FIELD_DP64(t, ID_AA64ISAR1, GPI, 0);
902
#include "hw/qdev-properties.h"
76
+ t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1);
903
+#include "cpregs.h"
77
cpu->isar.id_aa64isar1 = t;
904
78
905
79
t = cpu->isar.id_aa64pfr0;
906
#ifndef CONFIG_USER_ONLY
80
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
907
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
81
u = FIELD_DP32(u, ID_ISAR6, JSCVT, 1);
908
index XXXXXXX..XXXXXXX 100644
82
u = FIELD_DP32(u, ID_ISAR6, DP, 1);
909
--- a/target/arm/cpu_tcg.c
83
u = FIELD_DP32(u, ID_ISAR6, FHM, 1);
910
+++ b/target/arm/cpu_tcg.c
84
+ u = FIELD_DP32(u, ID_ISAR6, SB, 1);
911
@@ -XXX,XX +XXX,XX @@
85
cpu->isar.id_isar6 = u;
912
#if !defined(CONFIG_USER_ONLY)
86
913
#include "hw/boards.h"
87
/*
914
#endif
915
+#include "cpregs.h"
916
917
/* CPU models. These are not needed for the AArch64 linux-user build. */
918
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
919
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
920
index XXXXXXX..XXXXXXX 100644
921
--- a/target/arm/gdbstub.c
922
+++ b/target/arm/gdbstub.c
923
@@ -XXX,XX +XXX,XX @@
924
*/
925
#include "qemu/osdep.h"
926
#include "cpu.h"
927
-#include "internals.h"
928
#include "exec/gdbstub.h"
929
+#include "internals.h"
930
+#include "cpregs.h"
931
932
typedef struct RegisterSysregXmlParam {
933
CPUState *cs;
934
diff --git a/target/arm/helper.c b/target/arm/helper.c
935
index XXXXXXX..XXXXXXX 100644
936
--- a/target/arm/helper.c
937
+++ b/target/arm/helper.c
938
@@ -XXX,XX +XXX,XX @@
939
#include "exec/cpu_ldst.h"
940
#include "semihosting/common-semi.h"
941
#endif
942
+#include "cpregs.h"
943
944
#define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
945
#define PMCR_NUM_COUNTERS 4 /* QEMU IMPDEF choice */
946
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
947
index XXXXXXX..XXXXXXX 100644
948
--- a/target/arm/op_helper.c
949
+++ b/target/arm/op_helper.c
950
@@ -XXX,XX +XXX,XX @@
951
#include "internals.h"
952
#include "exec/exec-all.h"
953
#include "exec/cpu_ldst.h"
954
+#include "cpregs.h"
955
956
#define SIGNBIT (uint32_t)0x80000000
957
#define SIGNBIT64 ((uint64_t)1 << 63)
88
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
958
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
89
index XXXXXXX..XXXXXXX 100644
959
index XXXXXXX..XXXXXXX 100644
90
--- a/target/arm/translate-a64.c
960
--- a/target/arm/translate-a64.c
91
+++ b/target/arm/translate-a64.c
961
+++ b/target/arm/translate-a64.c
92
@@ -XXX,XX +XXX,XX @@ static void handle_sync(DisasContext *s, uint32_t insn,
962
@@ -XXX,XX +XXX,XX @@
93
reset_btype(s);
963
#include "translate.h"
94
gen_goto_tb(s, 0, s->pc);
964
#include "internals.h"
95
return;
965
#include "qemu/host-utils.h"
96
+
966
-
97
+ case 7: /* SB */
967
#include "semihosting/semihost.h"
98
+ if (crm != 0 || !dc_isar_feature(aa64_sb, s)) {
968
#include "exec/gen-icount.h"
99
+ goto do_unallocated;
969
-
100
+ }
970
#include "exec/helper-proto.h"
101
+ /*
971
#include "exec/helper-gen.h"
102
+ * TODO: There is no speculation barrier opcode for TCG;
972
#include "exec/log.h"
103
+ * MB and end the TB instead.
973
-
104
+ */
974
+#include "cpregs.h"
105
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
975
#include "translate-a64.h"
106
+ gen_goto_tb(s, 0, s->pc);
976
#include "qemu/atomic128.h"
107
+ return;
977
108
+
109
default:
110
+ do_unallocated:
111
unallocated_encoding(s);
112
return;
113
}
114
diff --git a/target/arm/translate.c b/target/arm/translate.c
978
diff --git a/target/arm/translate.c b/target/arm/translate.c
115
index XXXXXXX..XXXXXXX 100644
979
index XXXXXXX..XXXXXXX 100644
116
--- a/target/arm/translate.c
980
--- a/target/arm/translate.c
117
+++ b/target/arm/translate.c
981
+++ b/target/arm/translate.c
118
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
982
@@ -XXX,XX +XXX,XX @@
119
*/
983
#include "qemu/bitops.h"
120
gen_goto_tb(s, 0, s->pc & ~1);
984
#include "arm_ldst.h"
121
return;
985
#include "semihosting/semihost.h"
122
+ case 7: /* sb */
986
-
123
+ if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
987
#include "exec/helper-proto.h"
124
+ goto illegal_op;
988
#include "exec/helper-gen.h"
125
+ }
989
-
126
+ /*
990
#include "exec/log.h"
127
+ * TODO: There is no speculation barrier opcode
991
+#include "cpregs.h"
128
+ * for TCG; MB and end the TB instead.
992
129
+ */
993
130
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
994
#define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
131
+ gen_goto_tb(s, 0, s->pc & ~1);
132
+ return;
133
default:
134
goto illegal_op;
135
}
136
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
137
*/
138
gen_goto_tb(s, 0, s->pc & ~1);
139
break;
140
+ case 7: /* sb */
141
+ if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
142
+ goto illegal_op;
143
+ }
144
+ /*
145
+ * TODO: There is no speculation barrier opcode
146
+ * for TCG; MB and end the TB instead.
147
+ */
148
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
149
+ gen_goto_tb(s, 0, s->pc & ~1);
150
+ break;
151
default:
152
goto illegal_op;
153
}
154
--
995
--
155
2.20.1
996
2.25.1
156
997
157
998
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 EL0+UMA check is unique to DAIF. While SPSel had avoided the
3
Rearrange the values of the enumerators of CPAccessResult
4
check by nature of already checking EL >= 1, the other post v8.0
4
so that we may directly extract the target el. For the two
5
extensions to MSR (imm) allow EL0 and do not require UMA. Avoid
5
special cases in access_check_cp_reg, use CPAccessResult.
6
the unconditional write to pc and use raise_exception_ra to unwind.
7
6
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20190301200501.16533-5-richard.henderson@linaro.org
10
Message-id: 20220501055028.646596-3-richard.henderson@linaro.org
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
12
---
13
target/arm/helper-a64.h | 3 +++
13
target/arm/cpregs.h | 26 ++++++++++++--------
14
target/arm/helper.h | 1 -
14
target/arm/op_helper.c | 56 +++++++++++++++++++++---------------------
15
target/arm/internals.h | 15 ++++++++++++++
15
2 files changed, 44 insertions(+), 38 deletions(-)
16
target/arm/helper-a64.c | 30 +++++++++++++++++++++++++++
17
target/arm/op_helper.c | 42 --------------------------------------
18
target/arm/translate-a64.c | 41 ++++++++++++++++++++++---------------
19
6 files changed, 73 insertions(+), 59 deletions(-)
20
16
21
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
17
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
22
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper-a64.h
19
--- a/target/arm/cpregs.h
24
+++ b/target/arm/helper-a64.h
20
+++ b/target/arm/cpregs.h
25
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static inline bool cptype_valid(int cptype)
26
DEF_HELPER_FLAGS_2(udiv64, TCG_CALL_NO_RWG_SE, i64, i64, i64)
22
typedef enum CPAccessResult {
27
DEF_HELPER_FLAGS_2(sdiv64, TCG_CALL_NO_RWG_SE, s64, s64, s64)
23
/* Access is permitted */
28
DEF_HELPER_FLAGS_1(rbit64, TCG_CALL_NO_RWG_SE, i64, i64)
24
CP_ACCESS_OK = 0,
29
+DEF_HELPER_2(msr_i_spsel, void, env, i32)
30
+DEF_HELPER_2(msr_i_daifset, void, env, i32)
31
+DEF_HELPER_2(msr_i_daifclear, void, env, i32)
32
DEF_HELPER_3(vfp_cmph_a64, i64, f16, f16, ptr)
33
DEF_HELPER_3(vfp_cmpeh_a64, i64, f16, f16, ptr)
34
DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr)
35
diff --git a/target/arm/helper.h b/target/arm/helper.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/helper.h
38
+++ b/target/arm/helper.h
39
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(get_cp_reg, i32, env, ptr)
40
DEF_HELPER_3(set_cp_reg64, void, env, ptr, i64)
41
DEF_HELPER_2(get_cp_reg64, i64, env, ptr)
42
43
-DEF_HELPER_3(msr_i_pstate, void, env, i32, i32)
44
DEF_HELPER_1(clear_pstate_ss, void, env)
45
46
DEF_HELPER_2(get_r13_banked, i32, env, i32)
47
diff --git a/target/arm/internals.h b/target/arm/internals.h
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/internals.h
50
+++ b/target/arm/internals.h
51
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
52
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
53
ARMMMUIdx mmu_idx, bool data);
54
55
+static inline int exception_target_el(CPUARMState *env)
56
+{
57
+ int target_el = MAX(1, arm_current_el(env));
58
+
25
+
59
+ /*
26
+ /*
60
+ * No such thing as secure EL1 if EL3 is aarch32,
27
+ * Combined with one of the following, the low 2 bits indicate the
61
+ * so update the target EL to EL3 in this case.
28
+ * target exception level. If 0, the exception is taken to the usual
29
+ * target EL (EL1 or PL1 if in EL0, otherwise to the current EL).
62
+ */
30
+ */
63
+ if (arm_is_secure(env) && !arm_el_is_aa64(env, 3) && target_el == 1) {
31
+ CP_ACCESS_EL_MASK = 3,
64
+ target_el = 3;
65
+ }
66
+
32
+
67
+ return target_el;
33
/*
68
+}
34
* Access fails due to a configurable trap or enable which would
35
* result in a categorized exception syndrome giving information about
36
* the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6,
37
- * 0xc or 0x18). The exception is taken to the usual target EL (EL1 or
38
- * PL1 if in EL0, otherwise to the current EL).
39
+ * 0xc or 0x18).
40
*/
41
- CP_ACCESS_TRAP = 1,
42
+ CP_ACCESS_TRAP = (1 << 2),
43
+ CP_ACCESS_TRAP_EL2 = CP_ACCESS_TRAP | 2,
44
+ CP_ACCESS_TRAP_EL3 = CP_ACCESS_TRAP | 3,
69
+
45
+
70
#endif
46
/*
71
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
47
* Access fails and results in an exception syndrome 0x0 ("uncategorized").
72
index XXXXXXX..XXXXXXX 100644
48
* Note that this is not a catch-all case -- the set of cases which may
73
--- a/target/arm/helper-a64.c
49
* result in this failure is specifically defined by the architecture.
74
+++ b/target/arm/helper-a64.c
50
*/
75
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(rbit64)(uint64_t x)
51
- CP_ACCESS_TRAP_UNCATEGORIZED = 2,
76
return revbit64(x);
52
- /* As CP_ACCESS_TRAP, but for traps directly to EL2 or EL3 */
77
}
53
- CP_ACCESS_TRAP_EL2 = 3,
78
54
- CP_ACCESS_TRAP_EL3 = 4,
79
+void HELPER(msr_i_spsel)(CPUARMState *env, uint32_t imm)
55
- /* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */
80
+{
56
- CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5,
81
+ update_spsel(env, imm);
57
- CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6,
82
+}
58
+ CP_ACCESS_TRAP_UNCATEGORIZED = (2 << 2),
83
+
59
+ CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = CP_ACCESS_TRAP_UNCATEGORIZED | 2,
84
+static void daif_check(CPUARMState *env, uint32_t op,
60
+ CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = CP_ACCESS_TRAP_UNCATEGORIZED | 3,
85
+ uint32_t imm, uintptr_t ra)
61
} CPAccessResult;
86
+{
62
87
+ /* DAIF update to PSTATE. This is OK from EL0 only if UMA is set. */
63
typedef struct ARMCPRegInfo ARMCPRegInfo;
88
+ if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) {
89
+ raise_exception_ra(env, EXCP_UDEF,
90
+ syn_aa64_sysregtrap(0, extract32(op, 0, 3),
91
+ extract32(op, 3, 3), 4,
92
+ imm, 0x1f, 0),
93
+ exception_target_el(env), ra);
94
+ }
95
+}
96
+
97
+void HELPER(msr_i_daifset)(CPUARMState *env, uint32_t imm)
98
+{
99
+ daif_check(env, 0x1e, imm, GETPC());
100
+ env->daif |= (imm << 6) & PSTATE_DAIF;
101
+}
102
+
103
+void HELPER(msr_i_daifclear)(CPUARMState *env, uint32_t imm)
104
+{
105
+ daif_check(env, 0x1f, imm, GETPC());
106
+ env->daif &= ~((imm << 6) & PSTATE_DAIF);
107
+}
108
+
109
/* Convert a softfloat float_relation_ (as returned by
110
* the float*_compare functions) to the correct ARM
111
* NZCV flag state.
112
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
64
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
113
index XXXXXXX..XXXXXXX 100644
65
index XXXXXXX..XXXXXXX 100644
114
--- a/target/arm/op_helper.c
66
--- a/target/arm/op_helper.c
115
+++ b/target/arm/op_helper.c
67
+++ b/target/arm/op_helper.c
116
@@ -XXX,XX +XXX,XX @@ void raise_exception_ra(CPUARMState *env, uint32_t excp, uint32_t syndrome,
68
@@ -XXX,XX +XXX,XX @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome,
117
cpu_loop_exit_restore(cs, ra);
69
uint32_t isread)
118
}
119
120
-static int exception_target_el(CPUARMState *env)
121
-{
122
- int target_el = MAX(1, arm_current_el(env));
123
-
124
- /* No such thing as secure EL1 if EL3 is aarch32, so update the target EL
125
- * to EL3 in this case.
126
- */
127
- if (arm_is_secure(env) && !arm_el_is_aa64(env, 3) && target_el == 1) {
128
- target_el = 3;
129
- }
130
-
131
- return target_el;
132
-}
133
-
134
uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def, void *vn,
135
uint32_t maxindex)
136
{
70
{
137
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(get_cp_reg64)(CPUARMState *env, void *rip)
71
const ARMCPRegInfo *ri = rip;
138
return res;
72
+ CPAccessResult res = CP_ACCESS_OK;
139
}
73
int target_el;
140
74
141
-void HELPER(msr_i_pstate)(CPUARMState *env, uint32_t op, uint32_t imm)
75
if (arm_feature(env, ARM_FEATURE_XSCALE) && ri->cp < 14
142
-{
76
&& extract32(env->cp15.c15_cpar, ri->cp, 1) == 0) {
143
- /* MSR_i to update PSTATE. This is OK from EL0 only if UMA is set.
144
- * Note that SPSel is never OK from EL0; we rely on handle_msr_i()
145
- * to catch that case at translate time.
146
- */
147
- if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) {
148
- uint32_t syndrome = syn_aa64_sysregtrap(0, extract32(op, 0, 3),
149
- extract32(op, 3, 3), 4,
150
- imm, 0x1f, 0);
151
- raise_exception(env, EXCP_UDEF, syndrome, exception_target_el(env));
77
- raise_exception(env, EXCP_UDEF, syndrome, exception_target_el(env));
152
- }
78
+ res = CP_ACCESS_TRAP;
153
-
79
+ goto fail;
154
- switch (op) {
80
}
155
- case 0x05: /* SPSel */
81
156
- update_spsel(env, imm);
82
/*
157
- break;
83
@@ -XXX,XX +XXX,XX @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome,
158
- case 0x1e: /* DAIFSet */
84
mask &= ~((1 << 4) | (1 << 14));
159
- env->daif |= (imm << 6) & PSTATE_DAIF;
85
160
- break;
86
if (env->cp15.hstr_el2 & mask) {
161
- case 0x1f: /* DAIFClear */
87
- target_el = 2;
162
- env->daif &= ~((imm << 6) & PSTATE_DAIF);
88
- goto exept;
163
- break;
89
+ res = CP_ACCESS_TRAP_EL2;
164
- default:
90
+ goto fail;
165
- g_assert_not_reached();
166
- }
167
-}
168
-
169
void HELPER(clear_pstate_ss)(CPUARMState *env)
170
{
171
env->pstate &= ~PSTATE_SS;
172
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/target/arm/translate-a64.c
175
+++ b/target/arm/translate-a64.c
176
@@ -XXX,XX +XXX,XX @@ static void handle_sync(DisasContext *s, uint32_t insn,
177
static void handle_msr_i(DisasContext *s, uint32_t insn,
178
unsigned int op1, unsigned int op2, unsigned int crm)
179
{
180
+ TCGv_i32 t1;
181
int op = op1 << 3 | op2;
182
+
183
+ /* End the TB by default, chaining is ok. */
184
+ s->base.is_jmp = DISAS_TOO_MANY;
185
+
186
switch (op) {
187
case 0x05: /* SPSel */
188
if (s->current_el == 0) {
189
- unallocated_encoding(s);
190
- return;
191
+ goto do_unallocated;
192
}
91
}
193
- /* fall through */
92
}
194
- case 0x1e: /* DAIFSet */
93
195
- case 0x1f: /* DAIFClear */
94
- if (!ri->accessfn) {
196
- {
95
+ if (ri->accessfn) {
197
- TCGv_i32 tcg_imm = tcg_const_i32(crm);
96
+ res = ri->accessfn(env, ri, isread);
198
- TCGv_i32 tcg_op = tcg_const_i32(op);
97
+ }
199
- gen_a64_set_pc_im(s->pc - 4);
98
+ if (likely(res == CP_ACCESS_OK)) {
200
- gen_helper_msr_i_pstate(cpu_env, tcg_op, tcg_imm);
201
- tcg_temp_free_i32(tcg_imm);
202
- tcg_temp_free_i32(tcg_op);
203
- /* For DAIFClear, exit the cpu loop to re-evaluate pending IRQs. */
204
- gen_a64_set_pc_im(s->pc);
205
- s->base.is_jmp = (op == 0x1f ? DISAS_EXIT : DISAS_JUMP);
206
+ t1 = tcg_const_i32(crm & PSTATE_SP);
207
+ gen_helper_msr_i_spsel(cpu_env, t1);
208
+ tcg_temp_free_i32(t1);
209
break;
210
- }
211
+
212
+ case 0x1e: /* DAIFSet */
213
+ t1 = tcg_const_i32(crm);
214
+ gen_helper_msr_i_daifset(cpu_env, t1);
215
+ tcg_temp_free_i32(t1);
216
+ break;
217
+
218
+ case 0x1f: /* DAIFClear */
219
+ t1 = tcg_const_i32(crm);
220
+ gen_helper_msr_i_daifclear(cpu_env, t1);
221
+ tcg_temp_free_i32(t1);
222
+ /* For DAIFClear, exit the cpu loop to re-evaluate pending IRQs. */
223
+ s->base.is_jmp = DISAS_UPDATE;
224
+ break;
225
+
226
default:
227
+ do_unallocated:
228
unallocated_encoding(s);
229
return;
99
return;
230
}
100
}
101
102
- switch (ri->accessfn(env, ri, isread)) {
103
- case CP_ACCESS_OK:
104
- return;
105
+ fail:
106
+ switch (res & ~CP_ACCESS_EL_MASK) {
107
case CP_ACCESS_TRAP:
108
- target_el = exception_target_el(env);
109
- break;
110
- case CP_ACCESS_TRAP_EL2:
111
- /* Requesting a trap to EL2 when we're in EL3 is
112
- * a bug in the access function.
113
- */
114
- assert(arm_current_el(env) != 3);
115
- target_el = 2;
116
- break;
117
- case CP_ACCESS_TRAP_EL3:
118
- target_el = 3;
119
break;
120
case CP_ACCESS_TRAP_UNCATEGORIZED:
121
- target_el = exception_target_el(env);
122
- syndrome = syn_uncategorized();
123
- break;
124
- case CP_ACCESS_TRAP_UNCATEGORIZED_EL2:
125
- target_el = 2;
126
- syndrome = syn_uncategorized();
127
- break;
128
- case CP_ACCESS_TRAP_UNCATEGORIZED_EL3:
129
- target_el = 3;
130
syndrome = syn_uncategorized();
131
break;
132
default:
133
g_assert_not_reached();
134
}
135
136
-exept:
137
+ target_el = res & CP_ACCESS_EL_MASK;
138
+ switch (target_el) {
139
+ case 0:
140
+ target_el = exception_target_el(env);
141
+ break;
142
+ case 2:
143
+ assert(arm_current_el(env) != 3);
144
+ assert(arm_is_el2_enabled(env));
145
+ break;
146
+ case 3:
147
+ assert(arm_feature(env, ARM_FEATURE_EL3));
148
+ break;
149
+ default:
150
+ /* No "direct" traps to EL1 */
151
+ g_assert_not_reached();
152
+ }
153
+
154
raise_exception(env, EXCP_UDEF, syndrome, target_el);
155
}
156
231
--
157
--
232
2.20.1
158
2.25.1
233
159
234
160
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
3
Remove a possible source of error by removing REGINFO_SENTINEL
4
and using ARRAY_SIZE (convinently hidden inside a macro) to
5
find the end of the set of regs being registered or modified.
6
7
The space saved by not having the extra array element reduces
8
the executable's .data.rel.ro section by about 9k.
9
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20190301200501.16533-9-richard.henderson@linaro.org
13
Message-id: 20220501055028.646596-4-richard.henderson@linaro.org
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
15
---
9
target/arm/cpu.h | 5 ++++
16
target/arm/cpregs.h | 53 +++++++++---------
10
target/arm/cpu64.c | 2 +-
17
hw/arm/pxa2xx.c | 1 -
11
target/arm/translate-a64.c | 58 ++++++++++++++++++++++++++++++++++++++
18
hw/arm/pxa2xx_pic.c | 1 -
12
3 files changed, 64 insertions(+), 1 deletion(-)
19
hw/intc/arm_gicv3_cpuif.c | 5 --
20
hw/intc/arm_gicv3_kvm.c | 1 -
21
target/arm/cpu64.c | 1 -
22
target/arm/cpu_tcg.c | 4 --
23
target/arm/helper.c | 111 ++++++++------------------------------
24
8 files changed, 48 insertions(+), 129 deletions(-)
13
25
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
26
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
15
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
28
--- a/target/arm/cpregs.h
17
+++ b/target/arm/cpu.h
29
+++ b/target/arm/cpregs.h
18
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_condm_4(const ARMISARegisters *id)
30
@@ -XXX,XX +XXX,XX @@
19
return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) != 0;
31
#define ARM_CP_NO_GDB 0x4000
32
#define ARM_CP_RAISES_EXC 0x8000
33
#define ARM_CP_NEWEL 0x10000
34
-/* Used only as a terminator for ARMCPRegInfo lists */
35
-#define ARM_CP_SENTINEL 0xfffff
36
/* Mask of only the flag bits in a type field */
37
#define ARM_CP_FLAG_MASK 0x1f0ff
38
39
@@ -XXX,XX +XXX,XX @@ enum {
40
ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
41
};
42
43
-/*
44
- * Return true if cptype is a valid type field. This is used to try to
45
- * catch errors where the sentinel has been accidentally left off the end
46
- * of a list of registers.
47
- */
48
-static inline bool cptype_valid(int cptype)
49
-{
50
- return ((cptype & ~ARM_CP_FLAG_MASK) == 0)
51
- || ((cptype & ARM_CP_SPECIAL) &&
52
- ((cptype & ~ARM_CP_FLAG_MASK) <= ARM_LAST_SPECIAL));
53
-}
54
-
55
/*
56
* Access rights:
57
* We define bits for Read and Write access for what rev C of the v7-AR ARM ARM
58
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
59
#define CPREG_FIELD64(env, ri) \
60
(*(uint64_t *)((char *)(env) + (ri)->fieldoffset))
61
62
-#define REGINFO_SENTINEL { .type = ARM_CP_SENTINEL }
63
+void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu, const ARMCPRegInfo *reg,
64
+ void *opaque);
65
66
-void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
67
- const ARMCPRegInfo *regs, void *opaque);
68
-void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
69
- const ARMCPRegInfo *regs, void *opaque);
70
-static inline void define_arm_cp_regs(ARMCPU *cpu, const ARMCPRegInfo *regs)
71
-{
72
- define_arm_cp_regs_with_opaque(cpu, regs, 0);
73
-}
74
static inline void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *regs)
75
{
76
- define_one_arm_cp_reg_with_opaque(cpu, regs, 0);
77
+ define_one_arm_cp_reg_with_opaque(cpu, regs, NULL);
20
}
78
}
21
22
+static inline bool isar_feature_aa64_condm_5(const ARMISARegisters *id)
23
+{
24
+ return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) >= 2;
25
+}
26
+
79
+
27
static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id)
80
+void define_arm_cp_regs_with_opaque_len(ARMCPU *cpu, const ARMCPRegInfo *regs,
28
{
81
+ void *opaque, size_t len);
29
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0;
82
+
83
+#define define_arm_cp_regs_with_opaque(CPU, REGS, OPAQUE) \
84
+ do { \
85
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(REGS) == 0); \
86
+ define_arm_cp_regs_with_opaque_len(CPU, REGS, OPAQUE, \
87
+ ARRAY_SIZE(REGS)); \
88
+ } while (0)
89
+
90
+#define define_arm_cp_regs(CPU, REGS) \
91
+ define_arm_cp_regs_with_opaque(CPU, REGS, NULL)
92
+
93
const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp);
94
95
/*
96
@@ -XXX,XX +XXX,XX @@ typedef struct ARMCPRegUserSpaceInfo {
97
uint64_t fixed_bits;
98
} ARMCPRegUserSpaceInfo;
99
100
-#define REGUSERINFO_SENTINEL { .name = NULL }
101
+void modify_arm_cp_regs_with_len(ARMCPRegInfo *regs, size_t regs_len,
102
+ const ARMCPRegUserSpaceInfo *mods,
103
+ size_t mods_len);
104
105
-void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods);
106
+#define modify_arm_cp_regs(REGS, MODS) \
107
+ do { \
108
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(REGS) == 0); \
109
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(MODS) == 0); \
110
+ modify_arm_cp_regs_with_len(REGS, ARRAY_SIZE(REGS), \
111
+ MODS, ARRAY_SIZE(MODS)); \
112
+ } while (0)
113
114
/* CPWriteFn that can be used to implement writes-ignored behaviour */
115
void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
116
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/hw/arm/pxa2xx.c
119
+++ b/hw/arm/pxa2xx.c
120
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pxa_cp_reginfo[] = {
121
{ .name = "PWRMODE", .cp = 14, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 0,
122
.access = PL1_RW, .type = ARM_CP_IO,
123
.readfn = arm_cp_read_zero, .writefn = pxa2xx_pwrmode_write },
124
- REGINFO_SENTINEL
125
};
126
127
static void pxa2xx_setup_cp14(PXA2xxState *s)
128
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
129
index XXXXXXX..XXXXXXX 100644
130
--- a/hw/arm/pxa2xx_pic.c
131
+++ b/hw/arm/pxa2xx_pic.c
132
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pxa_pic_cp_reginfo[] = {
133
REGINFO_FOR_PIC_CP("ICLR2", 8),
134
REGINFO_FOR_PIC_CP("ICFP2", 9),
135
REGINFO_FOR_PIC_CP("ICPR2", 0xa),
136
- REGINFO_SENTINEL
137
};
138
139
static const MemoryRegionOps pxa2xx_pic_ops = {
140
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/hw/intc/arm_gicv3_cpuif.c
143
+++ b/hw/intc/arm_gicv3_cpuif.c
144
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
145
.readfn = icc_igrpen1_el3_read,
146
.writefn = icc_igrpen1_el3_write,
147
},
148
- REGINFO_SENTINEL
149
};
150
151
static uint64_t ich_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
152
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_hcr_reginfo[] = {
153
.readfn = ich_vmcr_read,
154
.writefn = ich_vmcr_write,
155
},
156
- REGINFO_SENTINEL
157
};
158
159
static const ARMCPRegInfo gicv3_cpuif_ich_apxr1_reginfo[] = {
160
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_ich_apxr1_reginfo[] = {
161
.readfn = ich_ap_read,
162
.writefn = ich_ap_write,
163
},
164
- REGINFO_SENTINEL
165
};
166
167
static const ARMCPRegInfo gicv3_cpuif_ich_apxr23_reginfo[] = {
168
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_ich_apxr23_reginfo[] = {
169
.readfn = ich_ap_read,
170
.writefn = ich_ap_write,
171
},
172
- REGINFO_SENTINEL
173
};
174
175
static void gicv3_cpuif_el_change_hook(ARMCPU *cpu, void *opaque)
176
@@ -XXX,XX +XXX,XX @@ void gicv3_init_cpuif(GICv3State *s)
177
.readfn = ich_lr_read,
178
.writefn = ich_lr_write,
179
},
180
- REGINFO_SENTINEL
181
};
182
define_arm_cp_regs(cpu, lr_regset);
183
}
184
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
185
index XXXXXXX..XXXXXXX 100644
186
--- a/hw/intc/arm_gicv3_kvm.c
187
+++ b/hw/intc/arm_gicv3_kvm.c
188
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
189
*/
190
.resetfn = arm_gicv3_icc_reset,
191
},
192
- REGINFO_SENTINEL
193
};
194
195
/**
30
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
196
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
31
index XXXXXXX..XXXXXXX 100644
197
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu64.c
198
--- a/target/arm/cpu64.c
33
+++ b/target/arm/cpu64.c
199
+++ b/target/arm/cpu64.c
34
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
200
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortex_a72_a57_a53_cp_reginfo[] = {
35
t = FIELD_DP64(t, ID_AA64ISAR0, SM4, 1);
201
{ .name = "L2MERRSR",
36
t = FIELD_DP64(t, ID_AA64ISAR0, DP, 1);
202
.cp = 15, .opc1 = 3, .crm = 15,
37
t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 1);
203
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
38
- t = FIELD_DP64(t, ID_AA64ISAR0, TS, 1);
204
- REGINFO_SENTINEL
39
+ t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* v8.5-CondM */
205
};
40
cpu->isar.id_aa64isar0 = t;
206
41
207
static void aarch64_a57_initfn(Object *obj)
42
t = cpu->isar.id_aa64isar1;
208
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
43
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
44
index XXXXXXX..XXXXXXX 100644
209
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/translate-a64.c
210
--- a/target/arm/cpu_tcg.c
46
+++ b/target/arm/translate-a64.c
211
+++ b/target/arm/cpu_tcg.c
47
@@ -XXX,XX +XXX,XX @@ static void handle_sync(DisasContext *s, uint32_t insn,
212
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
213
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
214
{ .name = "L2AUXCR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
215
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
216
- REGINFO_SENTINEL
217
};
218
219
static void cortex_a8_initfn(Object *obj)
220
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
221
.access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
222
{ .name = "TLB_ATTR", .cp = 15, .crn = 15, .crm = 7, .opc1 = 5, .opc2 = 2,
223
.access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
224
- REGINFO_SENTINEL
225
};
226
227
static void cortex_a9_initfn(Object *obj)
228
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
229
#endif
230
{ .name = "L2ECTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 3,
231
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
232
- REGINFO_SENTINEL
233
};
234
235
static void cortex_a7_initfn(Object *obj)
236
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
237
.access = PL1_RW, .type = ARM_CP_CONST },
238
{ .name = "DCACHE_INVAL", .cp = 15, .opc1 = 0, .crn = 15, .crm = 5,
239
.opc2 = 0, .access = PL1_W, .type = ARM_CP_NOP },
240
- REGINFO_SENTINEL
241
};
242
243
static void cortex_r5_initfn(Object *obj)
244
diff --git a/target/arm/helper.c b/target/arm/helper.c
245
index XXXXXXX..XXXXXXX 100644
246
--- a/target/arm/helper.c
247
+++ b/target/arm/helper.c
248
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cp_reginfo[] = {
249
.secure = ARM_CP_SECSTATE_S,
250
.fieldoffset = offsetof(CPUARMState, cp15.contextidr_s),
251
.resetvalue = 0, .writefn = contextidr_write, .raw_writefn = raw_write, },
252
- REGINFO_SENTINEL
253
};
254
255
static const ARMCPRegInfo not_v8_cp_reginfo[] = {
256
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo not_v8_cp_reginfo[] = {
257
{ .name = "CACHEMAINT", .cp = 15, .crn = 7, .crm = CP_ANY,
258
.opc1 = 0, .opc2 = CP_ANY, .access = PL1_W,
259
.type = ARM_CP_NOP | ARM_CP_OVERRIDE },
260
- REGINFO_SENTINEL
261
};
262
263
static const ARMCPRegInfo not_v6_cp_reginfo[] = {
264
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo not_v6_cp_reginfo[] = {
265
*/
266
{ .name = "WFI_v5", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 = 2,
267
.access = PL1_W, .type = ARM_CP_WFI },
268
- REGINFO_SENTINEL
269
};
270
271
static const ARMCPRegInfo not_v7_cp_reginfo[] = {
272
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo not_v7_cp_reginfo[] = {
273
.opc1 = 0, .opc2 = 0, .access = PL1_RW, .type = ARM_CP_NOP },
274
{ .name = "NMRR", .cp = 15, .crn = 10, .crm = 2,
275
.opc1 = 0, .opc2 = 1, .access = PL1_RW, .type = ARM_CP_NOP },
276
- REGINFO_SENTINEL
277
};
278
279
static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri,
280
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
281
.crn = 1, .crm = 0, .opc1 = 0, .opc2 = 2, .accessfn = cpacr_access,
282
.access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.cpacr_el1),
283
.resetfn = cpacr_reset, .writefn = cpacr_write, .readfn = cpacr_read },
284
- REGINFO_SENTINEL
285
};
286
287
typedef struct pm_event {
288
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
289
{ .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
290
.type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
291
.writefn = tlbimvaa_write },
292
- REGINFO_SENTINEL
293
};
294
295
static const ARMCPRegInfo v7mp_cp_reginfo[] = {
296
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v7mp_cp_reginfo[] = {
297
{ .name = "TLBIMVAAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3,
298
.type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
299
.writefn = tlbimvaa_is_write },
300
- REGINFO_SENTINEL
301
};
302
303
static const ARMCPRegInfo pmovsset_cp_reginfo[] = {
304
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmovsset_cp_reginfo[] = {
305
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
306
.writefn = pmovsset_write,
307
.raw_writefn = raw_write },
308
- REGINFO_SENTINEL
309
};
310
311
static void teecr_write(CPUARMState *env, const ARMCPRegInfo *ri,
312
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo t2ee_cp_reginfo[] = {
313
{ .name = "TEEHBR", .cp = 14, .crn = 1, .crm = 0, .opc1 = 6, .opc2 = 0,
314
.access = PL0_RW, .fieldoffset = offsetof(CPUARMState, teehbr),
315
.accessfn = teehbr_access, .resetvalue = 0 },
316
- REGINFO_SENTINEL
317
};
318
319
static const ARMCPRegInfo v6k_cp_reginfo[] = {
320
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v6k_cp_reginfo[] = {
321
.bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tpidrprw_s),
322
offsetoflow32(CPUARMState, cp15.tpidrprw_ns) },
323
.resetvalue = 0 },
324
- REGINFO_SENTINEL
325
};
326
327
#ifndef CONFIG_USER_ONLY
328
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
329
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_SEC].cval),
330
.writefn = gt_sec_cval_write, .raw_writefn = raw_write,
331
},
332
- REGINFO_SENTINEL
333
};
334
335
static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
336
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
337
.access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
338
.readfn = gt_virt_cnt_read,
339
},
340
- REGINFO_SENTINEL
341
};
342
343
#endif
344
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vapa_cp_reginfo[] = {
345
.access = PL1_W, .accessfn = ats_access,
346
.writefn = ats_write, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC },
347
#endif
348
- REGINFO_SENTINEL
349
};
350
351
/* Return basic MPU access permission bits. */
352
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmsav7_cp_reginfo[] = {
353
.fieldoffset = offsetof(CPUARMState, pmsav7.rnr[M_REG_NS]),
354
.writefn = pmsav7_rgnr_write,
355
.resetfn = arm_cp_reset_ignore },
356
- REGINFO_SENTINEL
357
};
358
359
static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
360
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
361
{ .name = "946_PRBS7", .cp = 15, .crn = 6, .crm = 7, .opc1 = 0,
362
.opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
363
.fieldoffset = offsetof(CPUARMState, cp15.c6_region[7]) },
364
- REGINFO_SENTINEL
365
};
366
367
static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
368
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vmsa_pmsa_cp_reginfo[] = {
369
.access = PL1_RW, .accessfn = access_tvm_trvm,
370
.fieldoffset = offsetof(CPUARMState, cp15.far_el[1]),
371
.resetvalue = 0, },
372
- REGINFO_SENTINEL
373
};
374
375
static const ARMCPRegInfo vmsa_cp_reginfo[] = {
376
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
377
/* No offsetoflow32 -- pass the entire TCR to writefn/raw_writefn. */
378
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.tcr_el[3]),
379
offsetof(CPUARMState, cp15.tcr_el[1])} },
380
- REGINFO_SENTINEL
381
};
382
383
/* Note that unlike TTBCR, writing to TTBCR2 does not require flushing
384
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo omap_cp_reginfo[] = {
385
{ .name = "C9", .cp = 15, .crn = 9,
386
.crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW,
387
.type = ARM_CP_CONST | ARM_CP_OVERRIDE, .resetvalue = 0 },
388
- REGINFO_SENTINEL
389
};
390
391
static void xscale_cpar_write(CPUARMState *env, const ARMCPRegInfo *ri,
392
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo xscale_cp_reginfo[] = {
393
{ .name = "XSCALE_UNLOCK_DCACHE",
394
.cp = 15, .opc1 = 0, .crn = 9, .crm = 2, .opc2 = 1,
395
.access = PL1_W, .type = ARM_CP_NOP },
396
- REGINFO_SENTINEL
397
};
398
399
static const ARMCPRegInfo dummy_c15_cp_reginfo[] = {
400
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo dummy_c15_cp_reginfo[] = {
401
.access = PL1_RW,
402
.type = ARM_CP_CONST | ARM_CP_NO_RAW | ARM_CP_OVERRIDE,
403
.resetvalue = 0 },
404
- REGINFO_SENTINEL
405
};
406
407
static const ARMCPRegInfo cache_dirty_status_cp_reginfo[] = {
408
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cache_dirty_status_cp_reginfo[] = {
409
{ .name = "CDSR", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 6,
410
.access = PL1_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW,
411
.resetvalue = 0 },
412
- REGINFO_SENTINEL
413
};
414
415
static const ARMCPRegInfo cache_block_ops_cp_reginfo[] = {
416
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cache_block_ops_cp_reginfo[] = {
417
.access = PL0_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
418
{ .name = "CIDCR", .cp = 15, .crm = 14, .opc1 = 0,
419
.access = PL1_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
420
- REGINFO_SENTINEL
421
};
422
423
static const ARMCPRegInfo cache_test_clean_cp_reginfo[] = {
424
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cache_test_clean_cp_reginfo[] = {
425
{ .name = "TCI_DCACHE", .cp = 15, .crn = 7, .crm = 14, .opc1 = 0, .opc2 = 3,
426
.access = PL0_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW,
427
.resetvalue = (1 << 30) },
428
- REGINFO_SENTINEL
429
};
430
431
static const ARMCPRegInfo strongarm_cp_reginfo[] = {
432
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo strongarm_cp_reginfo[] = {
433
.crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY,
434
.access = PL1_RW, .resetvalue = 0,
435
.type = ARM_CP_CONST | ARM_CP_OVERRIDE | ARM_CP_NO_RAW },
436
- REGINFO_SENTINEL
437
};
438
439
static uint64_t midr_read(CPUARMState *env, const ARMCPRegInfo *ri)
440
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
441
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s),
442
offsetof(CPUARMState, cp15.ttbr1_ns) },
443
.writefn = vmsa_ttbr_write, },
444
- REGINFO_SENTINEL
445
};
446
447
static uint64_t aa64_fpcr_read(CPUARMState *env, const ARMCPRegInfo *ri)
448
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
449
.access = PL1_RW, .accessfn = access_trap_aa32s_el1,
450
.writefn = sdcr_write,
451
.fieldoffset = offsetoflow32(CPUARMState, cp15.mdcr_el3) },
452
- REGINFO_SENTINEL
453
};
454
455
/* Used to describe the behaviour of EL2 regs when EL2 does not exist. */
456
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
457
.type = ARM_CP_CONST,
458
.cp = 15, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 2,
459
.access = PL2_RW, .resetvalue = 0 },
460
- REGINFO_SENTINEL
461
};
462
463
/* Ditto, but for registers which exist in ARMv8 but not v7 */
464
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_v8_cp_reginfo[] = {
465
.cp = 15, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 4,
466
.access = PL2_RW,
467
.type = ARM_CP_CONST, .resetvalue = 0 },
468
- REGINFO_SENTINEL
469
};
470
471
static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_mask)
472
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
473
.cp = 15, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 3,
474
.access = PL2_RW,
475
.fieldoffset = offsetof(CPUARMState, cp15.hstr_el2) },
476
- REGINFO_SENTINEL
477
};
478
479
static const ARMCPRegInfo el2_v8_cp_reginfo[] = {
480
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_v8_cp_reginfo[] = {
481
.access = PL2_RW,
482
.fieldoffset = offsetofhigh32(CPUARMState, cp15.hcr_el2),
483
.writefn = hcr_writehigh },
484
- REGINFO_SENTINEL
485
};
486
487
static CPAccessResult sel2_access(CPUARMState *env, const ARMCPRegInfo *ri,
488
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_sec_cp_reginfo[] = {
489
.opc0 = 3, .opc1 = 4, .crn = 2, .crm = 6, .opc2 = 2,
490
.access = PL2_RW, .accessfn = sel2_access,
491
.fieldoffset = offsetof(CPUARMState, cp15.vstcr_el2) },
492
- REGINFO_SENTINEL
493
};
494
495
static CPAccessResult nsacr_access(CPUARMState *env, const ARMCPRegInfo *ri,
496
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
497
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 5,
498
.access = PL3_W, .type = ARM_CP_NO_RAW,
499
.writefn = tlbi_aa64_vae3_write },
500
- REGINFO_SENTINEL
501
};
502
503
#ifndef CONFIG_USER_ONLY
504
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
505
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
506
.access = PL1_RW, .accessfn = access_tda,
507
.type = ARM_CP_NOP },
508
- REGINFO_SENTINEL
509
};
510
511
static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
512
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
513
.access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 },
514
{ .name = "DBGDSAR", .cp = 14, .crm = 2, .opc1 = 0,
515
.access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 },
516
- REGINFO_SENTINEL
517
};
518
519
/* Return the exception level to which exceptions should be taken
520
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
521
.fieldoffset = offsetof(CPUARMState, cp15.dbgbcr[i]),
522
.writefn = dbgbcr_write, .raw_writefn = raw_write
523
},
524
- REGINFO_SENTINEL
525
};
526
define_arm_cp_regs(cpu, dbgregs);
527
}
528
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
529
.fieldoffset = offsetof(CPUARMState, cp15.dbgwcr[i]),
530
.writefn = dbgwcr_write, .raw_writefn = raw_write
531
},
532
- REGINFO_SENTINEL
533
};
534
define_arm_cp_regs(cpu, dbgregs);
535
}
536
@@ -XXX,XX +XXX,XX @@ static void define_pmu_regs(ARMCPU *cpu)
537
.type = ARM_CP_IO,
538
.readfn = pmevtyper_readfn, .writefn = pmevtyper_writefn,
539
.raw_writefn = pmevtyper_rawwrite },
540
- REGINFO_SENTINEL
541
};
542
define_arm_cp_regs(cpu, pmev_regs);
543
g_free(pmevcntr_name);
544
@@ -XXX,XX +XXX,XX @@ static void define_pmu_regs(ARMCPU *cpu)
545
.cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 5,
546
.access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
547
.resetvalue = extract64(cpu->pmceid1, 32, 32) },
548
- REGINFO_SENTINEL
549
};
550
define_arm_cp_regs(cpu, v81_pmu_regs);
551
}
552
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo lor_reginfo[] = {
553
.opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 7,
554
.access = PL1_R, .accessfn = access_lor_ns,
555
.type = ARM_CP_CONST, .resetvalue = 0 },
556
- REGINFO_SENTINEL
557
};
558
559
#ifdef TARGET_AARCH64
560
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pauth_reginfo[] = {
561
.opc0 = 3, .opc1 = 0, .crn = 2, .crm = 1, .opc2 = 3,
562
.access = PL1_RW, .accessfn = access_pauth,
563
.fieldoffset = offsetof(CPUARMState, keys.apib.hi) },
564
- REGINFO_SENTINEL
565
};
566
567
static const ARMCPRegInfo tlbirange_reginfo[] = {
568
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbirange_reginfo[] = {
569
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 6, .opc2 = 5,
570
.access = PL3_W, .type = ARM_CP_NO_RAW,
571
.writefn = tlbi_aa64_rvae3_write },
572
- REGINFO_SENTINEL
573
};
574
575
static const ARMCPRegInfo tlbios_reginfo[] = {
576
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbios_reginfo[] = {
577
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 5,
578
.access = PL3_W, .type = ARM_CP_NO_RAW,
579
.writefn = tlbi_aa64_vae3is_write },
580
- REGINFO_SENTINEL
581
};
582
583
static uint64_t rndr_readfn(CPUARMState *env, const ARMCPRegInfo *ri)
584
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo rndr_reginfo[] = {
585
.type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END | ARM_CP_IO,
586
.opc0 = 3, .opc1 = 3, .crn = 2, .crm = 4, .opc2 = 1,
587
.access = PL0_R, .readfn = rndr_readfn },
588
- REGINFO_SENTINEL
589
};
590
591
#ifndef CONFIG_USER_ONLY
592
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo dcpop_reg[] = {
593
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 12, .opc2 = 1,
594
.access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END,
595
.accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn },
596
- REGINFO_SENTINEL
597
};
598
599
static const ARMCPRegInfo dcpodp_reg[] = {
600
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo dcpodp_reg[] = {
601
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 13, .opc2 = 1,
602
.access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END,
603
.accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn },
604
- REGINFO_SENTINEL
605
};
606
#endif /*CONFIG_USER_ONLY*/
607
608
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo mte_reginfo[] = {
609
{ .name = "DC_CIGDSW", .state = ARM_CP_STATE_AA64,
610
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 6,
611
.type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw },
612
- REGINFO_SENTINEL
613
};
614
615
static const ARMCPRegInfo mte_tco_ro_reginfo[] = {
616
{ .name = "TCO", .state = ARM_CP_STATE_AA64,
617
.opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 7,
618
.type = ARM_CP_CONST, .access = PL0_RW, },
619
- REGINFO_SENTINEL
620
};
621
622
static const ARMCPRegInfo mte_el0_cacheop_reginfo[] = {
623
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo mte_el0_cacheop_reginfo[] = {
624
.accessfn = aa64_zva_access,
625
#endif
626
},
627
- REGINFO_SENTINEL
628
};
629
630
#endif
631
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo predinv_reginfo[] = {
632
{ .name = "CPPRCTX", .state = ARM_CP_STATE_AA32,
633
.cp = 15, .opc1 = 0, .crn = 7, .crm = 3, .opc2 = 7,
634
.type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
635
- REGINFO_SENTINEL
636
};
637
638
static uint64_t ccsidr2_read(CPUARMState *env, const ARMCPRegInfo *ri)
639
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo ccsidr2_reginfo[] = {
640
.access = PL1_R,
641
.accessfn = access_aa64_tid2,
642
.readfn = ccsidr2_read, .type = ARM_CP_NO_RAW },
643
- REGINFO_SENTINEL
644
};
645
646
static CPAccessResult access_aa64_tid3(CPUARMState *env, const ARMCPRegInfo *ri,
647
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo jazelle_regs[] = {
648
.cp = 14, .crn = 2, .crm = 0, .opc1 = 7, .opc2 = 0,
649
.accessfn = access_joscr_jmcr,
650
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
651
- REGINFO_SENTINEL
652
};
653
654
static const ARMCPRegInfo vhe_reginfo[] = {
655
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
656
.access = PL2_RW, .accessfn = e2h_access,
657
.writefn = gt_virt_cval_write, .raw_writefn = raw_write },
658
#endif
659
- REGINFO_SENTINEL
660
};
661
662
#ifndef CONFIG_USER_ONLY
663
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo ats1e1_reginfo[] = {
664
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
665
.access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
666
.writefn = ats_write64 },
667
- REGINFO_SENTINEL
668
};
669
670
static const ARMCPRegInfo ats1cp_reginfo[] = {
671
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo ats1cp_reginfo[] = {
672
.cp = 15, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
673
.access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
674
.writefn = ats_write },
675
- REGINFO_SENTINEL
676
};
677
#endif
678
679
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo actlr2_hactlr2_reginfo[] = {
680
.cp = 15, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 3,
681
.access = PL2_RW, .type = ARM_CP_CONST,
682
.resetvalue = 0 },
683
- REGINFO_SENTINEL
684
};
685
686
void register_cp_regs_for_features(ARMCPU *cpu)
687
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
688
.access = PL1_R, .type = ARM_CP_CONST,
689
.accessfn = access_aa32_tid3,
690
.resetvalue = cpu->isar.id_isar6 },
691
- REGINFO_SENTINEL
692
};
693
define_arm_cp_regs(cpu, v6_idregs);
694
define_arm_cp_regs(cpu, v6_cp_reginfo);
695
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
696
.opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 7,
697
.access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
698
.resetvalue = cpu->pmceid1 },
699
- REGINFO_SENTINEL
700
};
701
#ifdef CONFIG_USER_ONLY
702
ARMCPRegUserSpaceInfo v8_user_idregs[] = {
703
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
704
.exported_bits = 0x000000f0ffffffff },
705
{ .name = "ID_AA64ISAR*_EL1_RESERVED",
706
.is_glob = true },
707
- REGUSERINFO_SENTINEL
708
};
709
modify_arm_cp_regs(v8_idregs, v8_user_idregs);
710
#endif
711
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
712
.access = PL2_RW,
713
.resetvalue = vmpidr_def,
714
.fieldoffset = offsetof(CPUARMState, cp15.vmpidr_el2) },
715
- REGINFO_SENTINEL
716
};
717
define_arm_cp_regs(cpu, vpidr_regs);
718
define_arm_cp_regs(cpu, el2_cp_reginfo);
719
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
720
.access = PL2_RW, .accessfn = access_el3_aa32ns,
721
.type = ARM_CP_NO_RAW,
722
.writefn = arm_cp_write_ignore, .readfn = mpidr_read },
723
- REGINFO_SENTINEL
724
};
725
define_arm_cp_regs(cpu, vpidr_regs);
726
define_arm_cp_regs(cpu, el3_no_el2_cp_reginfo);
727
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
728
.raw_writefn = raw_write, .writefn = sctlr_write,
729
.fieldoffset = offsetof(CPUARMState, cp15.sctlr_el[3]),
730
.resetvalue = cpu->reset_sctlr },
731
- REGINFO_SENTINEL
732
};
733
734
define_arm_cp_regs(cpu, el3_regs);
735
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
736
{ .name = "DUMMY",
737
.cp = 15, .crn = 0, .crm = 7, .opc1 = 0, .opc2 = CP_ANY,
738
.access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
739
- REGINFO_SENTINEL
740
};
741
ARMCPRegInfo id_v8_midr_cp_reginfo[] = {
742
{ .name = "MIDR_EL1", .state = ARM_CP_STATE_BOTH,
743
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
744
.access = PL1_R,
745
.accessfn = access_aa64_tid1,
746
.type = ARM_CP_CONST, .resetvalue = cpu->revidr },
747
- REGINFO_SENTINEL
748
};
749
ARMCPRegInfo id_cp_reginfo[] = {
750
/* These are common to v8 and pre-v8 */
751
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
752
.access = PL1_R,
753
.accessfn = access_aa32_tid1,
754
.type = ARM_CP_CONST, .resetvalue = 0 },
755
- REGINFO_SENTINEL
756
};
757
/* TLBTR is specific to VMSA */
758
ARMCPRegInfo id_tlbtr_reginfo = {
759
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
760
{ .name = "MIDR_EL1",
761
.exported_bits = 0x00000000ffffffff },
762
{ .name = "REVIDR_EL1" },
763
- REGUSERINFO_SENTINEL
764
};
765
modify_arm_cp_regs(id_v8_midr_cp_reginfo, id_v8_user_midr_cp_reginfo);
766
#endif
767
if (arm_feature(env, ARM_FEATURE_OMAPCP) ||
768
arm_feature(env, ARM_FEATURE_STRONGARM)) {
769
- ARMCPRegInfo *r;
770
+ size_t i;
771
/* Register the blanket "writes ignored" value first to cover the
772
* whole space. Then update the specific ID registers to allow write
773
* access, so that they ignore writes rather than causing them to
774
* UNDEF.
775
*/
776
define_one_arm_cp_reg(cpu, &crn0_wi_reginfo);
777
- for (r = id_pre_v8_midr_cp_reginfo;
778
- r->type != ARM_CP_SENTINEL; r++) {
779
- r->access = PL1_RW;
780
+ for (i = 0; i < ARRAY_SIZE(id_pre_v8_midr_cp_reginfo); ++i) {
781
+ id_pre_v8_midr_cp_reginfo[i].access = PL1_RW;
782
}
783
- for (r = id_cp_reginfo; r->type != ARM_CP_SENTINEL; r++) {
784
- r->access = PL1_RW;
785
+ for (i = 0; i < ARRAY_SIZE(id_cp_reginfo); ++i) {
786
+ id_cp_reginfo[i].access = PL1_RW;
787
}
788
id_mpuir_reginfo.access = PL1_RW;
789
id_tlbtr_reginfo.access = PL1_RW;
790
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
791
{ .name = "MPIDR_EL1", .state = ARM_CP_STATE_BOTH,
792
.opc0 = 3, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 5,
793
.access = PL1_R, .readfn = mpidr_read, .type = ARM_CP_NO_RAW },
794
- REGINFO_SENTINEL
795
};
796
#ifdef CONFIG_USER_ONLY
797
ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
798
{ .name = "MPIDR_EL1",
799
.fixed_bits = 0x0000000080000000 },
800
- REGUSERINFO_SENTINEL
801
};
802
modify_arm_cp_regs(mpidr_cp_reginfo, mpidr_user_cp_reginfo);
803
#endif
804
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
805
.opc0 = 3, .opc1 = 6, .crn = 1, .crm = 0, .opc2 = 1,
806
.access = PL3_RW, .type = ARM_CP_CONST,
807
.resetvalue = 0 },
808
- REGINFO_SENTINEL
809
};
810
define_arm_cp_regs(cpu, auxcr_reginfo);
811
if (cpu_isar_feature(aa32_ac2, cpu)) {
812
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
813
.type = ARM_CP_CONST,
814
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 3, .opc2 = 0,
815
.access = PL1_R, .resetvalue = cpu->reset_cbar },
816
- REGINFO_SENTINEL
817
};
818
/* We don't implement a r/w 64 bit CBAR currently */
819
assert(arm_feature(env, ARM_FEATURE_CBAR_RO));
820
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
821
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.vbar_s),
822
offsetof(CPUARMState, cp15.vbar_ns) },
823
.resetvalue = 0 },
824
- REGINFO_SENTINEL
825
};
826
define_arm_cp_regs(cpu, vbar_cp_reginfo);
827
}
828
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
829
r->writefn);
830
}
831
}
832
- /* Bad type field probably means missing sentinel at end of reg list */
833
- assert(cptype_valid(r->type));
834
+
835
for (crm = crmmin; crm <= crmmax; crm++) {
836
for (opc1 = opc1min; opc1 <= opc1max; opc1++) {
837
for (opc2 = opc2min; opc2 <= opc2max; opc2++) {
838
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
48
}
839
}
49
}
840
}
50
841
51
+static void gen_xaflag(void)
842
-void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
52
+{
843
- const ARMCPRegInfo *regs, void *opaque)
53
+ TCGv_i32 z = tcg_temp_new_i32();
844
+/* Define a whole list of registers */
845
+void define_arm_cp_regs_with_opaque_len(ARMCPU *cpu, const ARMCPRegInfo *regs,
846
+ void *opaque, size_t len)
847
{
848
- /* Define a whole list of registers */
849
- const ARMCPRegInfo *r;
850
- for (r = regs; r->type != ARM_CP_SENTINEL; r++) {
851
- define_one_arm_cp_reg_with_opaque(cpu, r, opaque);
852
+ size_t i;
853
+ for (i = 0; i < len; ++i) {
854
+ define_one_arm_cp_reg_with_opaque(cpu, regs + i, opaque);
855
}
856
}
857
858
@@ -XXX,XX +XXX,XX @@ void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
859
* user-space cannot alter any values and dynamic values pertaining to
860
* execution state are hidden from user space view anyway.
861
*/
862
-void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods)
863
+void modify_arm_cp_regs_with_len(ARMCPRegInfo *regs, size_t regs_len,
864
+ const ARMCPRegUserSpaceInfo *mods,
865
+ size_t mods_len)
866
{
867
- const ARMCPRegUserSpaceInfo *m;
868
- ARMCPRegInfo *r;
869
-
870
- for (m = mods; m->name; m++) {
871
+ for (size_t mi = 0; mi < mods_len; ++mi) {
872
+ const ARMCPRegUserSpaceInfo *m = mods + mi;
873
GPatternSpec *pat = NULL;
54
+
874
+
55
+ tcg_gen_setcondi_i32(TCG_COND_EQ, z, cpu_ZF, 0);
875
if (m->is_glob) {
876
pat = g_pattern_spec_new(m->name);
877
}
878
- for (r = regs; r->type != ARM_CP_SENTINEL; r++) {
879
+ for (size_t ri = 0; ri < regs_len; ++ri) {
880
+ ARMCPRegInfo *r = regs + ri;
56
+
881
+
57
+ /*
882
if (pat && g_pattern_match_string(pat, r->name)) {
58
+ * (!C & !Z) << 31
883
r->type = ARM_CP_CONST;
59
+ * (!(C | Z)) << 31
884
r->access = PL0U_R;
60
+ * ~((C | Z) << 31)
61
+ * ~-(C | Z)
62
+ * (C | Z) - 1
63
+ */
64
+ tcg_gen_or_i32(cpu_NF, cpu_CF, z);
65
+ tcg_gen_subi_i32(cpu_NF, cpu_NF, 1);
66
+
67
+ /* !(Z & C) */
68
+ tcg_gen_and_i32(cpu_ZF, z, cpu_CF);
69
+ tcg_gen_xori_i32(cpu_ZF, cpu_ZF, 1);
70
+
71
+ /* (!C & Z) << 31 -> -(Z & ~C) */
72
+ tcg_gen_andc_i32(cpu_VF, z, cpu_CF);
73
+ tcg_gen_neg_i32(cpu_VF, cpu_VF);
74
+
75
+ /* C | Z */
76
+ tcg_gen_or_i32(cpu_CF, cpu_CF, z);
77
+
78
+ tcg_temp_free_i32(z);
79
+}
80
+
81
+static void gen_axflag(void)
82
+{
83
+ tcg_gen_sari_i32(cpu_VF, cpu_VF, 31); /* V ? -1 : 0 */
84
+ tcg_gen_andc_i32(cpu_CF, cpu_CF, cpu_VF); /* C & !V */
85
+
86
+ /* !(Z | V) -> !(!ZF | V) -> ZF & !V -> ZF & ~VF */
87
+ tcg_gen_andc_i32(cpu_ZF, cpu_ZF, cpu_VF);
88
+
89
+ tcg_gen_movi_i32(cpu_NF, 0);
90
+ tcg_gen_movi_i32(cpu_VF, 0);
91
+}
92
+
93
/* MSR (immediate) - move immediate to processor state field */
94
static void handle_msr_i(DisasContext *s, uint32_t insn,
95
unsigned int op1, unsigned int op2, unsigned int crm)
96
@@ -XXX,XX +XXX,XX @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
97
s->base.is_jmp = DISAS_NEXT;
98
break;
99
100
+ case 0x01: /* XAFlag */
101
+ if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
102
+ goto do_unallocated;
103
+ }
104
+ gen_xaflag();
105
+ s->base.is_jmp = DISAS_NEXT;
106
+ break;
107
+
108
+ case 0x02: /* AXFlag */
109
+ if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
110
+ goto do_unallocated;
111
+ }
112
+ gen_axflag();
113
+ s->base.is_jmp = DISAS_NEXT;
114
+ break;
115
+
116
case 0x05: /* SPSel */
117
if (s->current_el == 0) {
118
goto do_unallocated;
119
--
885
--
120
2.20.1
886
2.25.1
121
887
122
888
diff view generated by jsdifflib
1
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We introduce an helper to create a memory node.
3
These particular data structures are not modified at runtime.
4
4
5
Signed-off-by: Eric Auger <eric.auger@redhat.com>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220501055028.646596-5-richard.henderson@linaro.org
9
Message-id: 20190304101339.25970-2-eric.auger@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
hw/arm/boot.c | 54 ++++++++++++++++++++++++++++++++-------------------
11
target/arm/helper.c | 16 ++++++++--------
13
1 file changed, 34 insertions(+), 20 deletions(-)
12
1 file changed, 8 insertions(+), 8 deletions(-)
14
13
15
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/boot.c
16
--- a/target/arm/helper.c
18
+++ b/hw/arm/boot.c
17
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args_old(const struct arm_boot_info *info,
18
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
20
}
19
.resetvalue = cpu->pmceid1 },
21
}
20
};
22
21
#ifdef CONFIG_USER_ONLY
23
+static int fdt_add_memory_node(void *fdt, uint32_t acells, hwaddr mem_base,
22
- ARMCPRegUserSpaceInfo v8_user_idregs[] = {
24
+ uint32_t scells, hwaddr mem_len,
23
+ static const ARMCPRegUserSpaceInfo v8_user_idregs[] = {
25
+ int numa_node_id)
24
{ .name = "ID_AA64PFR0_EL1",
26
+{
25
.exported_bits = 0x000f000f00ff0000,
27
+ char *nodename;
26
.fixed_bits = 0x0000000000000011 },
28
+ int ret;
27
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
29
+
28
*/
30
+ nodename = g_strdup_printf("/memory@%" PRIx64, mem_base);
29
if (arm_feature(env, ARM_FEATURE_EL3)) {
31
+ qemu_fdt_add_subnode(fdt, nodename);
30
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
32
+ qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
31
- ARMCPRegInfo nsacr = {
33
+ ret = qemu_fdt_setprop_sized_cells(fdt, nodename, "reg", acells, mem_base,
32
+ static const ARMCPRegInfo nsacr = {
34
+ scells, mem_len);
33
.name = "NSACR", .type = ARM_CP_CONST,
35
+ if (ret < 0) {
34
.cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
36
+ goto out;
35
.access = PL1_RW, .accessfn = nsacr_access,
37
+ }
36
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
38
+
37
};
39
+ /* only set the NUMA ID if it is specified */
38
define_one_arm_cp_reg(cpu, &nsacr);
40
+ if (numa_node_id >= 0) {
39
} else {
41
+ ret = qemu_fdt_setprop_cell(fdt, nodename,
40
- ARMCPRegInfo nsacr = {
42
+ "numa-node-id", numa_node_id);
41
+ static const ARMCPRegInfo nsacr = {
43
+ }
42
.name = "NSACR",
44
+out:
43
.cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
45
+ g_free(nodename);
44
.access = PL3_RW | PL1_R,
46
+ return ret;
45
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
47
+}
48
+
49
static void fdt_add_psci_node(void *fdt)
50
{
51
uint32_t cpu_suspend_fn;
52
@@ -XXX,XX +XXX,XX @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
53
void *fdt = NULL;
54
int size, rc, n = 0;
55
uint32_t acells, scells;
56
- char *nodename;
57
unsigned int i;
58
hwaddr mem_base, mem_len;
59
char **node_path;
60
@@ -XXX,XX +XXX,XX @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
61
mem_base = binfo->loader_start;
62
for (i = 0; i < nb_numa_nodes; i++) {
63
mem_len = numa_info[i].node_mem;
64
- nodename = g_strdup_printf("/memory@%" PRIx64, mem_base);
65
- qemu_fdt_add_subnode(fdt, nodename);
66
- qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
67
- rc = qemu_fdt_setprop_sized_cells(fdt, nodename, "reg",
68
- acells, mem_base,
69
- scells, mem_len);
70
+ rc = fdt_add_memory_node(fdt, acells, mem_base,
71
+ scells, mem_len, i);
72
if (rc < 0) {
73
- fprintf(stderr, "couldn't set %s/reg for node %d\n", nodename,
74
- i);
75
+ fprintf(stderr, "couldn't add /memory@%"PRIx64" node\n",
76
+ mem_base);
77
goto fail;
78
}
79
80
- qemu_fdt_setprop_cell(fdt, nodename, "numa-node-id", i);
81
mem_base += mem_len;
82
- g_free(nodename);
83
}
46
}
84
} else {
47
} else {
85
- nodename = g_strdup_printf("/memory@%" PRIx64, binfo->loader_start);
48
if (arm_feature(env, ARM_FEATURE_V8)) {
86
- qemu_fdt_add_subnode(fdt, nodename);
49
- ARMCPRegInfo nsacr = {
87
- qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
50
+ static const ARMCPRegInfo nsacr = {
88
-
51
.name = "NSACR", .type = ARM_CP_CONST,
89
- rc = qemu_fdt_setprop_sized_cells(fdt, nodename, "reg",
52
.cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
90
- acells, binfo->loader_start,
53
.access = PL1_R,
91
- scells, binfo->ram_size);
54
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
92
+ rc = fdt_add_memory_node(fdt, acells, binfo->loader_start,
55
.access = PL1_R, .type = ARM_CP_CONST,
93
+ scells, binfo->ram_size, -1);
56
.resetvalue = cpu->pmsav7_dregion << 8
94
if (rc < 0) {
57
};
95
- fprintf(stderr, "couldn't set %s reg\n", nodename);
58
- ARMCPRegInfo crn0_wi_reginfo = {
96
+ fprintf(stderr, "couldn't add /memory@%"PRIx64" node\n",
59
+ static const ARMCPRegInfo crn0_wi_reginfo = {
97
+ binfo->loader_start);
60
.name = "CRN0_WI", .cp = 15, .crn = 0, .crm = CP_ANY,
98
goto fail;
61
.opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_W,
99
}
62
.type = ARM_CP_NOP | ARM_CP_OVERRIDE
100
- g_free(nodename);
63
};
64
#ifdef CONFIG_USER_ONLY
65
- ARMCPRegUserSpaceInfo id_v8_user_midr_cp_reginfo[] = {
66
+ static const ARMCPRegUserSpaceInfo id_v8_user_midr_cp_reginfo[] = {
67
{ .name = "MIDR_EL1",
68
.exported_bits = 0x00000000ffffffff },
69
{ .name = "REVIDR_EL1" },
70
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
71
.access = PL1_R, .readfn = mpidr_read, .type = ARM_CP_NO_RAW },
72
};
73
#ifdef CONFIG_USER_ONLY
74
- ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
75
+ static const ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
76
{ .name = "MPIDR_EL1",
77
.fixed_bits = 0x0000000080000000 },
78
};
79
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
101
}
80
}
102
81
103
rc = fdt_path_offset(fdt, "/chosen");
82
if (arm_feature(env, ARM_FEATURE_VBAR)) {
83
- ARMCPRegInfo vbar_cp_reginfo[] = {
84
+ static const ARMCPRegInfo vbar_cp_reginfo[] = {
85
{ .name = "VBAR", .state = ARM_CP_STATE_BOTH,
86
.opc0 = 3, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0,
87
.access = PL1_RW, .writefn = vbar_write,
104
--
88
--
105
2.20.1
89
2.25.1
106
90
107
91
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We do not need an out-of-line helper for manipulating bits in pstate.
3
Instead of defining ARM_CP_FLAG_MASK to remove flags,
4
While changing things, share the implementation of gen_ss_advance.
4
define ARM_CP_SPECIAL_MASK to isolate special cases.
5
Sort the specials to the low bits. Use an enum.
6
7
Split the large comment block so as to document each
8
value separately.
5
9
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20190301200501.16533-6-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20220501055028.646596-6-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
14
---
11
target/arm/helper.h | 2 --
15
target/arm/cpregs.h | 130 +++++++++++++++++++++++--------------
12
target/arm/translate.h | 34 ++++++++++++++++++++++++++++++++++
16
target/arm/cpu.c | 4 +-
13
target/arm/op_helper.c | 5 -----
17
target/arm/helper.c | 4 +-
14
target/arm/translate-a64.c | 11 -----------
18
target/arm/translate-a64.c | 6 +-
15
target/arm/translate.c | 11 -----------
19
target/arm/translate.c | 6 +-
16
5 files changed, 34 insertions(+), 29 deletions(-)
20
5 files changed, 92 insertions(+), 58 deletions(-)
17
21
18
diff --git a/target/arm/helper.h b/target/arm/helper.h
22
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
19
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.h
24
--- a/target/arm/cpregs.h
21
+++ b/target/arm/helper.h
25
+++ b/target/arm/cpregs.h
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(get_cp_reg, i32, env, ptr)
26
@@ -XXX,XX +XXX,XX @@
23
DEF_HELPER_3(set_cp_reg64, void, env, ptr, i64)
27
#define TARGET_ARM_CPREGS_H
24
DEF_HELPER_2(get_cp_reg64, i64, env, ptr)
28
25
29
/*
26
-DEF_HELPER_1(clear_pstate_ss, void, env)
30
- * ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
27
-
31
- * special-behaviour cp reg and bits [11..8] indicate what behaviour
28
DEF_HELPER_2(get_r13_banked, i32, env, i32)
32
- * it has. Otherwise it is a simple cp reg, where CONST indicates that
29
DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
33
- * TCG can assume the value to be constant (ie load at translate time)
30
34
- * and 64BIT indicates a 64 bit wide coprocessor register. SUPPRESS_TB_END
31
diff --git a/target/arm/translate.h b/target/arm/translate.h
35
- * indicates that the TB should not be ended after a write to this register
32
index XXXXXXX..XXXXXXX 100644
36
- * (the default is that the TB ends after cp writes). OVERRIDE permits
33
--- a/target/arm/translate.h
37
- * a register definition to override a previous definition for the
34
+++ b/target/arm/translate.h
38
- * same (cp, is64, crn, crm, opc1, opc2) tuple: either the new or the
35
@@ -XXX,XX +XXX,XX @@ static inline TCGv_i32 get_ahp_flag(void)
39
- * old must have the OVERRIDE bit set.
36
return ret;
40
- * ALIAS indicates that this register is an alias view of some underlying
37
}
41
- * state which is also visible via another register, and that the other
38
42
- * register is handling migration and reset; registers marked ALIAS will not be
39
+/* Set bits within PSTATE. */
43
- * migrated but may have their state set by syncing of register state from KVM.
40
+static inline void set_pstate_bits(uint32_t bits)
44
- * NO_RAW indicates that this register has no underlying state and does not
41
+{
45
- * support raw access for state saving/loading; it will not be used for either
42
+ TCGv_i32 p = tcg_temp_new_i32();
46
- * migration or KVM state synchronization. (Typically this is for "registers"
47
- * which are actually used as instructions for cache maintenance and so on.)
48
- * IO indicates that this register does I/O and therefore its accesses
49
- * need to be marked with gen_io_start() and also end the TB. In particular,
50
- * registers which implement clocks or timers require this.
51
- * RAISES_EXC is for when the read or write hook might raise an exception;
52
- * the generated code will synchronize the CPU state before calling the hook
53
- * so that it is safe for the hook to call raise_exception().
54
- * NEWEL is for writes to registers that might change the exception
55
- * level - typically on older ARM chips. For those cases we need to
56
- * re-read the new el when recomputing the translation flags.
57
+ * ARMCPRegInfo type field bits:
58
*/
59
-#define ARM_CP_SPECIAL 0x0001
60
-#define ARM_CP_CONST 0x0002
61
-#define ARM_CP_64BIT 0x0004
62
-#define ARM_CP_SUPPRESS_TB_END 0x0008
63
-#define ARM_CP_OVERRIDE 0x0010
64
-#define ARM_CP_ALIAS 0x0020
65
-#define ARM_CP_IO 0x0040
66
-#define ARM_CP_NO_RAW 0x0080
67
-#define ARM_CP_NOP (ARM_CP_SPECIAL | 0x0100)
68
-#define ARM_CP_WFI (ARM_CP_SPECIAL | 0x0200)
69
-#define ARM_CP_NZCV (ARM_CP_SPECIAL | 0x0300)
70
-#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400)
71
-#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | 0x0500)
72
-#define ARM_CP_DC_GVA (ARM_CP_SPECIAL | 0x0600)
73
-#define ARM_CP_DC_GZVA (ARM_CP_SPECIAL | 0x0700)
74
-#define ARM_LAST_SPECIAL ARM_CP_DC_GZVA
75
-#define ARM_CP_FPU 0x1000
76
-#define ARM_CP_SVE 0x2000
77
-#define ARM_CP_NO_GDB 0x4000
78
-#define ARM_CP_RAISES_EXC 0x8000
79
-#define ARM_CP_NEWEL 0x10000
80
-/* Mask of only the flag bits in a type field */
81
-#define ARM_CP_FLAG_MASK 0x1f0ff
82
+enum {
83
+ /*
84
+ * Register must be handled specially during translation.
85
+ * The method is one of the values below:
86
+ */
87
+ ARM_CP_SPECIAL_MASK = 0x000f,
88
+ /* Special: no change to PE state: writes ignored, reads ignored. */
89
+ ARM_CP_NOP = 0x0001,
90
+ /* Special: sysreg is WFI, for v5 and v6. */
91
+ ARM_CP_WFI = 0x0002,
92
+ /* Special: sysreg is NZCV. */
93
+ ARM_CP_NZCV = 0x0003,
94
+ /* Special: sysreg is CURRENTEL. */
95
+ ARM_CP_CURRENTEL = 0x0004,
96
+ /* Special: sysreg is DC ZVA or similar. */
97
+ ARM_CP_DC_ZVA = 0x0005,
98
+ ARM_CP_DC_GVA = 0x0006,
99
+ ARM_CP_DC_GZVA = 0x0007,
43
+
100
+
44
+ tcg_debug_assert(!(bits & CACHED_PSTATE_BITS));
101
+ /* Flag: reads produce resetvalue; writes ignored. */
45
+
102
+ ARM_CP_CONST = 1 << 4,
46
+ tcg_gen_ld_i32(p, cpu_env, offsetof(CPUARMState, pstate));
103
+ /* Flag: For ARM_CP_STATE_AA32, sysreg is 64-bit. */
47
+ tcg_gen_ori_i32(p, p, bits);
104
+ ARM_CP_64BIT = 1 << 5,
48
+ tcg_gen_st_i32(p, cpu_env, offsetof(CPUARMState, pstate));
105
+ /*
49
+ tcg_temp_free_i32(p);
106
+ * Flag: TB should not be ended after a write to this register
50
+}
107
+ * (the default is that the TB ends after cp writes).
51
+
108
+ */
52
+/* Clear bits within PSTATE. */
109
+ ARM_CP_SUPPRESS_TB_END = 1 << 6,
53
+static inline void clear_pstate_bits(uint32_t bits)
110
+ /*
54
+{
111
+ * Flag: Permit a register definition to override a previous definition
55
+ TCGv_i32 p = tcg_temp_new_i32();
112
+ * for the same (cp, is64, crn, crm, opc1, opc2) tuple: either the new
56
+
113
+ * or the old must have the ARM_CP_OVERRIDE bit set.
57
+ tcg_debug_assert(!(bits & CACHED_PSTATE_BITS));
114
+ */
58
+
115
+ ARM_CP_OVERRIDE = 1 << 7,
59
+ tcg_gen_ld_i32(p, cpu_env, offsetof(CPUARMState, pstate));
116
+ /*
60
+ tcg_gen_andi_i32(p, p, ~bits);
117
+ * Flag: Register is an alias view of some underlying state which is also
61
+ tcg_gen_st_i32(p, cpu_env, offsetof(CPUARMState, pstate));
118
+ * visible via another register, and that the other register is handling
62
+ tcg_temp_free_i32(p);
119
+ * migration and reset; registers marked ARM_CP_ALIAS will not be migrated
63
+}
120
+ * but may have their state set by syncing of register state from KVM.
64
+
121
+ */
65
+/* If the singlestep state is Active-not-pending, advance to Active-pending. */
122
+ ARM_CP_ALIAS = 1 << 8,
66
+static inline void gen_ss_advance(DisasContext *s)
123
+ /*
67
+{
124
+ * Flag: Register does I/O and therefore its accesses need to be marked
68
+ if (s->ss_active) {
125
+ * with gen_io_start() and also end the TB. In particular, registers which
69
+ s->pstate_ss = 0;
126
+ * implement clocks or timers require this.
70
+ clear_pstate_bits(PSTATE_SS);
127
+ */
71
+ }
128
+ ARM_CP_IO = 1 << 9,
72
+}
129
+ /*
73
130
+ * Flag: Register has no underlying state and does not support raw access
74
/* Vector operations shared between ARM and AArch64. */
131
+ * for state saving/loading; it will not be used for either migration or
75
extern const GVecGen3 bsl_op;
132
+ * KVM state synchronization. Typically this is for "registers" which are
76
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
133
+ * actually used as instructions for cache maintenance and so on.
77
index XXXXXXX..XXXXXXX 100644
134
+ */
78
--- a/target/arm/op_helper.c
135
+ ARM_CP_NO_RAW = 1 << 10,
79
+++ b/target/arm/op_helper.c
136
+ /*
80
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(get_cp_reg64)(CPUARMState *env, void *rip)
137
+ * Flag: The read or write hook might raise an exception; the generated
81
return res;
138
+ * code will synchronize the CPU state before calling the hook so that it
82
}
139
+ * is safe for the hook to call raise_exception().
83
140
+ */
84
-void HELPER(clear_pstate_ss)(CPUARMState *env)
141
+ ARM_CP_RAISES_EXC = 1 << 11,
85
-{
142
+ /*
86
- env->pstate &= ~PSTATE_SS;
143
+ * Flag: Writes to the sysreg might change the exception level - typically
87
-}
144
+ * on older ARM chips. For those cases we need to re-read the new el when
88
-
145
+ * recomputing the translation flags.
89
void HELPER(pre_hvc)(CPUARMState *env)
146
+ */
90
{
147
+ ARM_CP_NEWEL = 1 << 12,
91
ARMCPU *cpu = arm_env_get_cpu(env);
148
+ /*
149
+ * Flag: Access check for this sysreg is identical to accessing FPU state
150
+ * from an instruction: use translation fp_access_check().
151
+ */
152
+ ARM_CP_FPU = 1 << 13,
153
+ /*
154
+ * Flag: Access check for this sysreg is identical to accessing SVE state
155
+ * from an instruction: use translation sve_access_check().
156
+ */
157
+ ARM_CP_SVE = 1 << 14,
158
+ /* Flag: Do not expose in gdb sysreg xml. */
159
+ ARM_CP_NO_GDB = 1 << 15,
160
+};
161
162
/*
163
* Valid values for ARMCPRegInfo state field, indicating which of
164
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
165
index XXXXXXX..XXXXXXX 100644
166
--- a/target/arm/cpu.c
167
+++ b/target/arm/cpu.c
168
@@ -XXX,XX +XXX,XX @@ static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
169
ARMCPRegInfo *ri = value;
170
ARMCPU *cpu = opaque;
171
172
- if (ri->type & (ARM_CP_SPECIAL | ARM_CP_ALIAS)) {
173
+ if (ri->type & (ARM_CP_SPECIAL_MASK | ARM_CP_ALIAS)) {
174
return;
175
}
176
177
@@ -XXX,XX +XXX,XX @@ static void cp_reg_check_reset(gpointer key, gpointer value, gpointer opaque)
178
ARMCPU *cpu = opaque;
179
uint64_t oldvalue, newvalue;
180
181
- if (ri->type & (ARM_CP_SPECIAL | ARM_CP_ALIAS | ARM_CP_NO_RAW)) {
182
+ if (ri->type & (ARM_CP_SPECIAL_MASK | ARM_CP_ALIAS | ARM_CP_NO_RAW)) {
183
return;
184
}
185
186
diff --git a/target/arm/helper.c b/target/arm/helper.c
187
index XXXXXXX..XXXXXXX 100644
188
--- a/target/arm/helper.c
189
+++ b/target/arm/helper.c
190
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
191
* multiple times. Special registers (ie NOP/WFI) are
192
* never migratable and not even raw-accessible.
193
*/
194
- if ((r->type & ARM_CP_SPECIAL)) {
195
+ if (r->type & ARM_CP_SPECIAL_MASK) {
196
r2->type |= ARM_CP_NO_RAW;
197
}
198
if (((r->crm == CP_ANY) && crm != 0) ||
199
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
200
/* Check that the register definition has enough info to handle
201
* reads and writes if they are permitted.
202
*/
203
- if (!(r->type & (ARM_CP_SPECIAL|ARM_CP_CONST))) {
204
+ if (!(r->type & (ARM_CP_SPECIAL_MASK | ARM_CP_CONST))) {
205
if (r->access & PL3_R) {
206
assert((r->fieldoffset ||
207
(r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) ||
92
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
208
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
93
index XXXXXXX..XXXXXXX 100644
209
index XXXXXXX..XXXXXXX 100644
94
--- a/target/arm/translate-a64.c
210
--- a/target/arm/translate-a64.c
95
+++ b/target/arm/translate-a64.c
211
+++ b/target/arm/translate-a64.c
96
@@ -XXX,XX +XXX,XX @@ static void gen_exception_bkpt_insn(DisasContext *s, int offset,
212
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
97
s->base.is_jmp = DISAS_NORETURN;
213
}
98
}
214
99
215
/* Handle special cases first */
100
-static void gen_ss_advance(DisasContext *s)
216
- switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
101
-{
217
+ switch (ri->type & ARM_CP_SPECIAL_MASK) {
102
- /* If the singlestep state is Active-not-pending, advance to
218
+ case 0:
103
- * Active-pending.
219
+ break;
104
- */
220
case ARM_CP_NOP:
105
- if (s->ss_active) {
221
return;
106
- s->pstate_ss = 0;
222
case ARM_CP_NZCV:
107
- gen_helper_clear_pstate_ss(cpu_env);
223
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
108
- }
224
}
109
-}
225
return;
110
-
226
default:
111
static void gen_step_complete_exception(DisasContext *s)
227
- break;
112
{
228
+ g_assert_not_reached();
113
/* We just completed step of an insn. Move from Active-not-pending
229
}
230
if ((ri->type & ARM_CP_FPU) && !fp_access_check(s)) {
231
return;
114
diff --git a/target/arm/translate.c b/target/arm/translate.c
232
diff --git a/target/arm/translate.c b/target/arm/translate.c
115
index XXXXXXX..XXXXXXX 100644
233
index XXXXXXX..XXXXXXX 100644
116
--- a/target/arm/translate.c
234
--- a/target/arm/translate.c
117
+++ b/target/arm/translate.c
235
+++ b/target/arm/translate.c
118
@@ -XXX,XX +XXX,XX @@ static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
236
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
119
tcg_temp_free_i32(tcg_excp);
237
}
120
}
238
121
239
/* Handle special cases first */
122
-static void gen_ss_advance(DisasContext *s)
240
- switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
123
-{
241
+ switch (ri->type & ARM_CP_SPECIAL_MASK) {
124
- /* If the singlestep state is Active-not-pending, advance to
242
+ case 0:
125
- * Active-pending.
243
+ break;
126
- */
244
case ARM_CP_NOP:
127
- if (s->ss_active) {
245
return;
128
- s->pstate_ss = 0;
246
case ARM_CP_WFI:
129
- gen_helper_clear_pstate_ss(cpu_env);
247
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
130
- }
248
s->base.is_jmp = DISAS_WFI;
131
-}
249
return;
132
-
250
default:
133
static void gen_step_complete_exception(DisasContext *s)
251
- break;
134
{
252
+ g_assert_not_reached();
135
/* We just completed step of an insn. Move from Active-not-pending
253
}
254
255
if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
136
--
256
--
137
2.20.1
257
2.25.1
138
139
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This will allow sharing code that adjusts rmode beyond
3
Standardize on g_assert_not_reached() for "should not happen".
4
the existing users.
4
Retain abort() when preceeded by fprintf or error_report.
5
5
6
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190301200501.16533-10-richard.henderson@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20220501055028.646596-7-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
target/arm/translate-a64.c | 90 +++++++++++++++++++++-----------------
11
target/arm/helper.c | 7 +++----
13
1 file changed, 49 insertions(+), 41 deletions(-)
12
target/arm/hvf/hvf.c | 2 +-
13
target/arm/kvm-stub.c | 4 ++--
14
target/arm/kvm.c | 4 ++--
15
target/arm/machine.c | 4 ++--
16
target/arm/translate-a64.c | 4 ++--
17
target/arm/translate-neon.c | 2 +-
18
target/arm/translate.c | 4 ++--
19
8 files changed, 15 insertions(+), 16 deletions(-)
14
20
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
24
+++ b/target/arm/helper.c
25
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
26
break;
27
default:
28
/* broken reginfo with out-of-range opc1 */
29
- assert(false);
30
- break;
31
+ g_assert_not_reached();
32
}
33
/* assert our permissions are not too lax (stricter is fine) */
34
assert((r->access & ~mask) == 0);
35
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
36
break;
37
default:
38
/* Never happens, but compiler isn't smart enough to tell. */
39
- abort();
40
+ g_assert_not_reached();
41
}
42
}
43
*prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot);
44
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
45
break;
46
default:
47
/* Never happens, but compiler isn't smart enough to tell. */
48
- abort();
49
+ g_assert_not_reached();
50
}
51
}
52
if (domain_prot == 3) {
53
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/hvf/hvf.c
56
+++ b/target/arm/hvf/hvf.c
57
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *cpu)
58
/* we got kicked, no exit to process */
59
return 0;
60
default:
61
- assert(0);
62
+ g_assert_not_reached();
63
}
64
65
hvf_sync_vtimer(cpu);
66
diff --git a/target/arm/kvm-stub.c b/target/arm/kvm-stub.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/kvm-stub.c
69
+++ b/target/arm/kvm-stub.c
70
@@ -XXX,XX +XXX,XX @@
71
72
bool write_kvmstate_to_list(ARMCPU *cpu)
73
{
74
- abort();
75
+ g_assert_not_reached();
76
}
77
78
bool write_list_to_kvmstate(ARMCPU *cpu, int level)
79
{
80
- abort();
81
+ g_assert_not_reached();
82
}
83
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/target/arm/kvm.c
86
+++ b/target/arm/kvm.c
87
@@ -XXX,XX +XXX,XX @@ bool write_kvmstate_to_list(ARMCPU *cpu)
88
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
89
break;
90
default:
91
- abort();
92
+ g_assert_not_reached();
93
}
94
if (ret) {
95
ok = false;
96
@@ -XXX,XX +XXX,XX @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level)
97
r.addr = (uintptr_t)(cpu->cpreg_values + i);
98
break;
99
default:
100
- abort();
101
+ g_assert_not_reached();
102
}
103
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
104
if (ret) {
105
diff --git a/target/arm/machine.c b/target/arm/machine.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/machine.c
108
+++ b/target/arm/machine.c
109
@@ -XXX,XX +XXX,XX @@ static int cpu_pre_save(void *opaque)
110
if (kvm_enabled()) {
111
if (!write_kvmstate_to_list(cpu)) {
112
/* This should never fail */
113
- abort();
114
+ g_assert_not_reached();
115
}
116
117
/*
118
@@ -XXX,XX +XXX,XX @@ static int cpu_pre_save(void *opaque)
119
} else {
120
if (!write_cpustate_to_list(cpu, false)) {
121
/* This should never fail. */
122
- abort();
123
+ g_assert_not_reached();
124
}
125
}
126
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
127
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
16
index XXXXXXX..XXXXXXX 100644
128
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
129
--- a/target/arm/translate-a64.c
18
+++ b/target/arm/translate-a64.c
130
+++ b/target/arm/translate-a64.c
19
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
131
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
20
/* Floating-point data-processing (1 source) - single precision */
132
gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
21
static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
22
{
23
+ void (*gen_fpst)(TCGv_i32, TCGv_i32, TCGv_ptr);
24
+ TCGv_i32 tcg_op, tcg_res;
25
TCGv_ptr fpst;
26
- TCGv_i32 tcg_op;
27
- TCGv_i32 tcg_res;
28
+ int rmode = -1;
29
30
- fpst = get_fpstatus_ptr(false);
31
tcg_op = read_fp_sreg(s, rn);
32
tcg_res = tcg_temp_new_i32();
33
34
switch (opcode) {
35
case 0x0: /* FMOV */
36
tcg_gen_mov_i32(tcg_res, tcg_op);
37
- break;
38
+ goto done;
39
case 0x1: /* FABS */
40
gen_helper_vfp_abss(tcg_res, tcg_op);
41
- break;
42
+ goto done;
43
case 0x2: /* FNEG */
44
gen_helper_vfp_negs(tcg_res, tcg_op);
45
- break;
46
+ goto done;
47
case 0x3: /* FSQRT */
48
gen_helper_vfp_sqrts(tcg_res, tcg_op, cpu_env);
49
- break;
50
+ goto done;
51
case 0x8: /* FRINTN */
52
case 0x9: /* FRINTP */
53
case 0xa: /* FRINTM */
54
case 0xb: /* FRINTZ */
55
case 0xc: /* FRINTA */
56
- {
57
- TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
58
-
59
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
60
- gen_helper_rints(tcg_res, tcg_op, fpst);
61
-
62
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
63
- tcg_temp_free_i32(tcg_rmode);
64
+ rmode = arm_rmode_to_sf(opcode & 7);
65
+ gen_fpst = gen_helper_rints;
66
break;
67
- }
68
case 0xe: /* FRINTX */
69
- gen_helper_rints_exact(tcg_res, tcg_op, fpst);
70
+ gen_fpst = gen_helper_rints_exact;
71
break;
72
case 0xf: /* FRINTI */
73
- gen_helper_rints(tcg_res, tcg_op, fpst);
74
+ gen_fpst = gen_helper_rints;
75
break;
133
break;
76
default:
134
default:
77
- abort();
135
- abort();
78
+ g_assert_not_reached();
136
+ g_assert_not_reached();
79
}
137
}
80
138
81
- write_fp_sreg(s, rd, tcg_res);
139
write_fp_sreg(s, rd, tcg_res);
82
-
140
@@ -XXX,XX +XXX,XX @@ static void handle_fp_fcvt(DisasContext *s, int opcode,
83
+ fpst = get_fpstatus_ptr(false);
141
break;
84
+ if (rmode >= 0) {
142
}
85
+ TCGv_i32 tcg_rmode = tcg_const_i32(rmode);
143
default:
86
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
144
- abort();
87
+ gen_fpst(tcg_res, tcg_op, fpst);
145
+ g_assert_not_reached();
88
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
146
}
89
+ tcg_temp_free_i32(tcg_rmode);
90
+ } else {
91
+ gen_fpst(tcg_res, tcg_op, fpst);
92
+ }
93
tcg_temp_free_ptr(fpst);
94
+
95
+ done:
96
+ write_fp_sreg(s, rd, tcg_res);
97
tcg_temp_free_i32(tcg_op);
98
tcg_temp_free_i32(tcg_res);
99
}
147
}
100
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
148
101
/* Floating-point data-processing (1 source) - double precision */
149
diff --git a/target/arm/translate-neon.c b/target/arm/translate-neon.c
102
static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
150
index XXXXXXX..XXXXXXX 100644
103
{
151
--- a/target/arm/translate-neon.c
104
+ void (*gen_fpst)(TCGv_i64, TCGv_i64, TCGv_ptr);
152
+++ b/target/arm/translate-neon.c
105
+ TCGv_i64 tcg_op, tcg_res;
153
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a)
106
TCGv_ptr fpst;
154
}
107
- TCGv_i64 tcg_op;
108
- TCGv_i64 tcg_res;
109
+ int rmode = -1;
110
111
switch (opcode) {
112
case 0x0: /* FMOV */
113
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
114
return;
115
}
116
117
- fpst = get_fpstatus_ptr(false);
118
tcg_op = read_fp_dreg(s, rn);
119
tcg_res = tcg_temp_new_i64();
120
121
switch (opcode) {
122
case 0x1: /* FABS */
123
gen_helper_vfp_absd(tcg_res, tcg_op);
124
- break;
125
+ goto done;
126
case 0x2: /* FNEG */
127
gen_helper_vfp_negd(tcg_res, tcg_op);
128
- break;
129
+ goto done;
130
case 0x3: /* FSQRT */
131
gen_helper_vfp_sqrtd(tcg_res, tcg_op, cpu_env);
132
- break;
133
+ goto done;
134
case 0x8: /* FRINTN */
135
case 0x9: /* FRINTP */
136
case 0xa: /* FRINTM */
137
case 0xb: /* FRINTZ */
138
case 0xc: /* FRINTA */
139
- {
140
- TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
141
-
142
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
143
- gen_helper_rintd(tcg_res, tcg_op, fpst);
144
-
145
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
146
- tcg_temp_free_i32(tcg_rmode);
147
+ rmode = arm_rmode_to_sf(opcode & 7);
148
+ gen_fpst = gen_helper_rintd;
149
break;
150
- }
151
case 0xe: /* FRINTX */
152
- gen_helper_rintd_exact(tcg_res, tcg_op, fpst);
153
+ gen_fpst = gen_helper_rintd_exact;
154
break;
155
case 0xf: /* FRINTI */
156
- gen_helper_rintd(tcg_res, tcg_op, fpst);
157
+ gen_fpst = gen_helper_rintd;
158
break;
155
break;
159
default:
156
default:
160
- abort();
157
- abort();
161
+ g_assert_not_reached();
158
+ g_assert_not_reached();
162
}
159
}
163
160
if ((vd + a->stride * (nregs - 1)) > 31) {
164
- write_fp_dreg(s, rd, tcg_res);
161
/*
165
-
162
diff --git a/target/arm/translate.c b/target/arm/translate.c
166
+ fpst = get_fpstatus_ptr(false);
163
index XXXXXXX..XXXXXXX 100644
167
+ if (rmode >= 0) {
164
--- a/target/arm/translate.c
168
+ TCGv_i32 tcg_rmode = tcg_const_i32(rmode);
165
+++ b/target/arm/translate.c
169
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
166
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
170
+ gen_fpst(tcg_res, tcg_op, fpst);
167
offset = 4;
171
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
168
break;
172
+ tcg_temp_free_i32(tcg_rmode);
169
default:
173
+ } else {
170
- abort();
174
+ gen_fpst(tcg_res, tcg_op, fpst);
171
+ g_assert_not_reached();
175
+ }
172
}
176
tcg_temp_free_ptr(fpst);
173
tcg_gen_addi_i32(addr, addr, offset);
177
+
174
tmp = load_reg(s, 14);
178
+ done:
175
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
179
+ write_fp_dreg(s, rd, tcg_res);
176
offset = 0;
180
tcg_temp_free_i64(tcg_op);
177
break;
181
tcg_temp_free_i64(tcg_res);
178
default:
182
}
179
- abort();
180
+ g_assert_not_reached();
181
}
182
tcg_gen_addi_i32(addr, addr, offset);
183
gen_helper_set_r13_banked(cpu_env, tcg_constant_i32(mode), addr);
183
--
184
--
184
2.20.1
185
2.25.1
185
186
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Create a typedef as well, and use it in ARMCPRegInfo.
4
This won't be perfect for debugging, but it'll nicely
5
display the most common cases.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220501055028.646596-8-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/cpregs.h | 44 +++++++++++++++++++++++---------------------
13
target/arm/helper.c | 2 +-
14
2 files changed, 24 insertions(+), 22 deletions(-)
15
16
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpregs.h
19
+++ b/target/arm/cpregs.h
20
@@ -XXX,XX +XXX,XX @@ enum {
21
* described with these bits, then use a laxer set of restrictions, and
22
* do the more restrictive/complex check inside a helper function.
23
*/
24
-#define PL3_R 0x80
25
-#define PL3_W 0x40
26
-#define PL2_R (0x20 | PL3_R)
27
-#define PL2_W (0x10 | PL3_W)
28
-#define PL1_R (0x08 | PL2_R)
29
-#define PL1_W (0x04 | PL2_W)
30
-#define PL0_R (0x02 | PL1_R)
31
-#define PL0_W (0x01 | PL1_W)
32
+typedef enum {
33
+ PL3_R = 0x80,
34
+ PL3_W = 0x40,
35
+ PL2_R = 0x20 | PL3_R,
36
+ PL2_W = 0x10 | PL3_W,
37
+ PL1_R = 0x08 | PL2_R,
38
+ PL1_W = 0x04 | PL2_W,
39
+ PL0_R = 0x02 | PL1_R,
40
+ PL0_W = 0x01 | PL1_W,
41
42
-/*
43
- * For user-mode some registers are accessible to EL0 via a kernel
44
- * trap-and-emulate ABI. In this case we define the read permissions
45
- * as actually being PL0_R. However some bits of any given register
46
- * may still be masked.
47
- */
48
+ /*
49
+ * For user-mode some registers are accessible to EL0 via a kernel
50
+ * trap-and-emulate ABI. In this case we define the read permissions
51
+ * as actually being PL0_R. However some bits of any given register
52
+ * may still be masked.
53
+ */
54
#ifdef CONFIG_USER_ONLY
55
-#define PL0U_R PL0_R
56
+ PL0U_R = PL0_R,
57
#else
58
-#define PL0U_R PL1_R
59
+ PL0U_R = PL1_R,
60
#endif
61
62
-#define PL3_RW (PL3_R | PL3_W)
63
-#define PL2_RW (PL2_R | PL2_W)
64
-#define PL1_RW (PL1_R | PL1_W)
65
-#define PL0_RW (PL0_R | PL0_W)
66
+ PL3_RW = PL3_R | PL3_W,
67
+ PL2_RW = PL2_R | PL2_W,
68
+ PL1_RW = PL1_R | PL1_W,
69
+ PL0_RW = PL0_R | PL0_W,
70
+} CPAccessRights;
71
72
typedef enum CPAccessResult {
73
/* Access is permitted */
74
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
75
/* Register type: ARM_CP_* bits/values */
76
int type;
77
/* Access rights: PL*_[RW] */
78
- int access;
79
+ CPAccessRights access;
80
/* Security state: ARM_CP_SECSTATE_* bits/values */
81
int secure;
82
/*
83
diff --git a/target/arm/helper.c b/target/arm/helper.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/target/arm/helper.c
86
+++ b/target/arm/helper.c
87
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
88
* to encompass the generic architectural permission check.
89
*/
90
if (r->state != ARM_CP_STATE_AA32) {
91
- int mask = 0;
92
+ CPAccessRights mask;
93
switch (r->opc1) {
94
case 0:
95
/* min_EL EL1, but some accessible to EL0 via kernel ABI */
96
--
97
2.25.1
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Now we have the extended memory map (high IO regions beyond the
3
Give this enum a name and use in ARMCPRegInfo,
4
scalable RAM) and dynamic IPA range support at KVM/ARM level
4
add_cpreg_to_hashtable and define_one_arm_cp_reg_with_opaque.
5
we can bump the legacy 255GB initial RAM limit. The actual maximum
6
RAM size now depends on the physical CPU and host kernel, in
7
accelerated mode. In TCG mode, it depends on the VCPU
8
AA64MMFR0.PARANGE.
9
5
10
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20190304101339.25970-11-eric.auger@redhat.com
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220501055028.646596-9-richard.henderson@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
11
---
15
hw/arm/virt.c | 21 +--------------------
12
target/arm/cpregs.h | 6 +++---
16
1 file changed, 1 insertion(+), 20 deletions(-)
13
target/arm/helper.c | 6 ++++--
14
2 files changed, 7 insertions(+), 5 deletions(-)
17
15
18
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
16
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/virt.c
18
--- a/target/arm/cpregs.h
21
+++ b/hw/arm/virt.c
19
+++ b/target/arm/cpregs.h
22
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ enum {
23
21
* Note that we rely on the values of these enums as we iterate through
24
#define PLATFORM_BUS_NUM_IRQS 64
22
* the various states in some places.
25
23
*/
26
-/* RAM limit in GB. Since VIRT_MEM starts at the 1GB mark, this means
24
-enum {
27
- * RAM can go up to the 256GB mark, leaving 256GB of the physical
25
+typedef enum {
28
- * address space unallocated and free for future use between 256G and 512G.
26
ARM_CP_STATE_AA32 = 0,
29
- * If we need to provide more RAM to VMs in the future then we need to:
27
ARM_CP_STATE_AA64 = 1,
30
- * * allocate a second bank of RAM starting at 2TB and working up
28
ARM_CP_STATE_BOTH = 2,
31
- * * fix the DT and ACPI table generation code in QEMU to correctly
29
-};
32
- * report two split lumps of RAM to the guest
30
+} CPState;
33
- * * fix KVM in the host kernel to allow guests with >40 bit address spaces
31
34
- * (We don't want to fill all the way up to 512GB with RAM because
32
/*
35
- * we might want it for non-RAM purposes later. Conversely it seems
33
* ARM CP register secure state flags. These flags identify security state
36
- * reasonable to assume that anybody configuring a VM with a quarter
34
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
37
- * of a terabyte of RAM will be doing it on a host with more than a
35
uint8_t opc1;
38
- * terabyte of physical address space.)
36
uint8_t opc2;
39
- */
37
/* Execution state in which this register is visible: ARM_CP_STATE_* */
40
+/* Legacy RAM limit in GB (< version 4.0) */
38
- int state;
41
#define LEGACY_RAMLIMIT_GB 255
39
+ CPState state;
42
#define LEGACY_RAMLIMIT_BYTES (LEGACY_RAMLIMIT_GB * GiB)
40
/* Register type: ARM_CP_* bits/values */
43
41
int type;
44
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
42
/* Access rights: PL*_[RW] */
45
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
46
vms->smp_cpus = smp_cpus;
44
index XXXXXXX..XXXXXXX 100644
47
45
--- a/target/arm/helper.c
48
- if (machine->ram_size > vms->memmap[VIRT_MEM].size) {
46
+++ b/target/arm/helper.c
49
- error_report("mach-virt: cannot model more than %dGB RAM",
47
@@ -XXX,XX +XXX,XX @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
50
- LEGACY_RAMLIMIT_GB);
48
}
51
- exit(1);
49
52
- }
50
static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
53
-
51
- void *opaque, int state, int secstate,
54
if (vms->virt && kvm_enabled()) {
52
+ void *opaque, CPState state, int secstate,
55
error_report("mach-virt: KVM does not support providing "
53
int crm, int opc1, int opc2,
56
"Virtualization extensions to the guest CPU");
54
const char *name)
55
{
56
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
57
* bits; the ARM_CP_64BIT* flag applies only to the AArch32 view of
58
* the register, if any.
59
*/
60
- int crm, opc1, opc2, state;
61
+ int crm, opc1, opc2;
62
int crmmin = (r->crm == CP_ANY) ? 0 : r->crm;
63
int crmmax = (r->crm == CP_ANY) ? 15 : r->crm;
64
int opc1min = (r->opc1 == CP_ANY) ? 0 : r->opc1;
65
int opc1max = (r->opc1 == CP_ANY) ? 7 : r->opc1;
66
int opc2min = (r->opc2 == CP_ANY) ? 0 : r->opc2;
67
int opc2max = (r->opc2 == CP_ANY) ? 7 : r->opc2;
68
+ CPState state;
69
+
70
/* 64 bit registers have only CRm and Opc1 fields */
71
assert(!((r->type & ARM_CP_64BIT) && (r->opc2 || r->crn)));
72
/* op0 only exists in the AArch64 encodings */
57
--
73
--
58
2.20.1
74
2.25.1
59
75
60
76
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Add the kvm_arm_get_max_vm_ipa_size() helper that returns the
3
Give this enum a name and use in ARMCPRegInfo and add_cpreg_to_hashtable.
4
number of bits in the IPA address space supported by KVM.
4
Add the enumerator ARM_CP_SECSTATE_BOTH to clarify how 0
5
is handled in define_one_arm_cp_reg_with_opaque.
5
6
6
This capability needs to be known to create the VM with a
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
specific IPA max size (kvm_type passed along KVM_CREATE_VM ioctl.
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
9
Message-id: 20220501055028.646596-10-richard.henderson@linaro.org
9
Signed-off-by: Eric Auger <eric.auger@redhat.com>
10
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
11
Message-id: 20190304101339.25970-6-eric.auger@redhat.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
11
---
14
target/arm/kvm_arm.h | 13 +++++++++++++
12
target/arm/cpregs.h | 7 ++++---
15
target/arm/kvm.c | 10 ++++++++++
13
target/arm/helper.c | 7 +++++--
16
2 files changed, 23 insertions(+)
14
2 files changed, 9 insertions(+), 5 deletions(-)
17
15
18
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
16
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/kvm_arm.h
18
--- a/target/arm/cpregs.h
21
+++ b/target/arm/kvm_arm.h
19
+++ b/target/arm/cpregs.h
22
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf);
20
@@ -XXX,XX +XXX,XX @@ typedef enum {
21
* registered entry will only have one to identify whether the entry is secure
22
* or non-secure.
23
*/
23
*/
24
void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
24
-enum {
25
25
+typedef enum {
26
+/**
26
+ ARM_CP_SECSTATE_BOTH = 0, /* define one cpreg for each secstate */
27
+ * kvm_arm_get_max_vm_ipa_size - Returns the number of bits in the
27
ARM_CP_SECSTATE_S = (1 << 0), /* bit[0]: Secure state register */
28
+ * IPA address space supported by KVM
28
ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
29
+ *
29
-};
30
+ * @ms: Machine state handle
30
+} CPSecureState;
31
+ */
31
32
+int kvm_arm_get_max_vm_ipa_size(MachineState *ms);
32
/*
33
+
33
* Access rights:
34
/**
34
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
35
* kvm_arm_sync_mpstate_to_kvm
35
/* Access rights: PL*_[RW] */
36
* @cpu: ARMCPU
36
CPAccessRights access;
37
@@ -XXX,XX +XXX,XX @@ static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
37
/* Security state: ARM_CP_SECSTATE_* bits/values */
38
cpu->host_cpu_probe_failed = true;
38
- int secure;
39
+ CPSecureState secure;
40
/*
41
* The opaque pointer passed to define_arm_cp_regs_with_opaque() when
42
* this register was defined: can be used to hand data through to the
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/helper.c
46
+++ b/target/arm/helper.c
47
@@ -XXX,XX +XXX,XX @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
39
}
48
}
40
49
41
+static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
50
static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
42
+{
51
- void *opaque, CPState state, int secstate,
43
+ return -ENOENT;
52
+ void *opaque, CPState state,
44
+}
53
+ CPSecureState secstate,
45
+
54
int crm, int opc1, int opc2,
46
static inline int kvm_arm_vgic_probe(void)
55
const char *name)
47
{
56
{
48
return 0;
57
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
49
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
58
r->secure, crm, opc1, opc2,
50
index XXXXXXX..XXXXXXX 100644
59
r->name);
51
--- a/target/arm/kvm.c
60
break;
52
+++ b/target/arm/kvm.c
61
- default:
53
@@ -XXX,XX +XXX,XX @@
62
+ case ARM_CP_SECSTATE_BOTH:
54
#include "qemu/error-report.h"
63
name = g_strdup_printf("%s_S", r->name);
55
#include "sysemu/sysemu.h"
64
add_cpreg_to_hashtable(cpu, r, opaque, state,
56
#include "sysemu/kvm.h"
65
ARM_CP_SECSTATE_S,
57
+#include "sysemu/kvm_int.h"
66
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
58
#include "kvm_arm.h"
67
ARM_CP_SECSTATE_NS,
59
#include "cpu.h"
68
crm, opc1, opc2, r->name);
60
#include "trace.h"
69
break;
61
@@ -XXX,XX +XXX,XX @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
70
+ default:
62
env->features = arm_host_cpu_features.features;
71
+ g_assert_not_reached();
63
}
72
}
64
73
} else {
65
+int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
74
/* AArch64 registers get mapped to non-secure instance
66
+{
67
+ KVMState *s = KVM_STATE(ms->accelerator);
68
+ int ret;
69
+
70
+ ret = kvm_check_extension(s, KVM_CAP_ARM_VM_IPA_SIZE);
71
+ return ret > 0 ? ret : 40;
72
+}
73
+
74
int kvm_arch_init(MachineState *ms, KVMState *s)
75
{
76
/* For ARM interrupt delivery is always asynchronous,
77
--
75
--
78
2.20.1
76
2.25.1
79
80
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The machine RAM attributes will need to be analyzed during the
3
The new_key field is always non-zero -- drop the if.
4
configure_accelerator() process. especially kvm_type() arm64
5
machine callback will use them to know how many IPA/GPA bits are
6
needed to model the whole RAM range. So let's assign those machine
7
state fields before calling configure_accelerator.
8
4
9
Signed-off-by: Eric Auger <eric.auger@redhat.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
7
Message-id: 20220501055028.646596-11-richard.henderson@linaro.org
12
Message-id: 20190304101339.25970-7-eric.auger@redhat.com
8
[PMM: reinstated dropped PL3_RW mask]
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
10
---
15
vl.c | 6 +++---
11
target/arm/helper.c | 23 +++++++++++------------
16
1 file changed, 3 insertions(+), 3 deletions(-)
12
1 file changed, 11 insertions(+), 12 deletions(-)
17
13
18
diff --git a/vl.c b/vl.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
20
--- a/vl.c
16
--- a/target/arm/helper.c
21
+++ b/vl.c
17
+++ b/target/arm/helper.c
22
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
18
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
23
machine_opts = qemu_get_machine_opts();
19
24
qemu_opt_foreach(machine_opts, machine_set_property, current_machine,
20
for (i = 0; i < ARRAY_SIZE(aliases); i++) {
25
&error_fatal);
21
const struct E2HAlias *a = &aliases[i];
26
+ current_machine->ram_size = ram_size;
22
- ARMCPRegInfo *src_reg, *dst_reg;
27
+ current_machine->maxram_size = maxram_size;
23
+ ARMCPRegInfo *src_reg, *dst_reg, *new_reg;
28
+ current_machine->ram_slots = ram_slots;
24
+ uint32_t *new_key;
29
25
+ bool ok;
30
configure_accelerator(current_machine, argv[0]);
26
31
27
if (a->feature && !a->feature(&cpu->isar)) {
32
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
28
continue;
33
replay_checkpoint(CHECKPOINT_INIT);
29
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
34
qdev_machine_init();
30
g_assert(src_reg->opaque == NULL);
35
31
36
- current_machine->ram_size = ram_size;
32
/* Create alias before redirection so we dup the right data. */
37
- current_machine->maxram_size = maxram_size;
33
- if (a->new_key) {
38
- current_machine->ram_slots = ram_slots;
34
- ARMCPRegInfo *new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
39
current_machine->boot_order = boot_order;
35
- uint32_t *new_key = g_memdup(&a->new_key, sizeof(uint32_t));
40
36
- bool ok;
41
/* parse features once if machine provides default cpu_type */
37
+ new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
38
+ new_key = g_memdup(&a->new_key, sizeof(uint32_t));
39
40
- new_reg->name = a->new_name;
41
- new_reg->type |= ARM_CP_ALIAS;
42
- /* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */
43
- new_reg->access &= PL2_RW | PL3_RW;
44
+ new_reg->name = a->new_name;
45
+ new_reg->type |= ARM_CP_ALIAS;
46
+ /* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */
47
+ new_reg->access &= PL2_RW | PL3_RW;
48
49
- ok = g_hash_table_insert(cpu->cp_regs, new_key, new_reg);
50
- g_assert(ok);
51
- }
52
+ ok = g_hash_table_insert(cpu->cp_regs, new_key, new_reg);
53
+ g_assert(ok);
54
55
src_reg->opaque = dst_reg;
56
src_reg->orig_readfn = src_reg->readfn ?: raw_read;
42
--
57
--
43
2.20.1
58
2.25.1
44
45
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Cast the uint32_t key into a gpointer directly, which
4
allows us to avoid allocating storage for each key.
5
6
Use g_hash_table_lookup when we already have a gpointer
7
(e.g. for callbacks like count_cpreg), or when using
8
get_arm_cp_reginfo would require casting away const.
9
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20190301200501.16533-4-richard.henderson@linaro.org
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20220501055028.646596-12-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
14
---
8
target/arm/cpu.h | 13 ++++++++++-
15
target/arm/cpu.c | 4 ++--
9
target/arm/cpu.c | 1 +
16
target/arm/gdbstub.c | 2 +-
10
target/arm/cpu64.c | 2 ++
17
target/arm/helper.c | 41 ++++++++++++++++++-----------------------
11
target/arm/helper.c | 55 +++++++++++++++++++++++++++++++++++++++++++++
18
3 files changed, 21 insertions(+), 26 deletions(-)
12
4 files changed, 70 insertions(+), 1 deletion(-)
13
19
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
19
#define SCTLR_R (1U << 9) /* up to v6; RAZ in v7 */
20
#define SCTLR_UMA (1U << 9) /* v8 onward, AArch64 only */
21
#define SCTLR_F (1U << 10) /* up to v6 */
22
-#define SCTLR_SW (1U << 10) /* v7, RES0 in v8 */
23
+#define SCTLR_SW (1U << 10) /* v7 */
24
+#define SCTLR_EnRCTX (1U << 10) /* in v8.0-PredInv */
25
#define SCTLR_Z (1U << 11) /* in v7, RES1 in v8 */
26
#define SCTLR_EOS (1U << 11) /* v8.5-ExS */
27
#define SCTLR_I (1U << 12)
28
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_sb(const ARMISARegisters *id)
29
return FIELD_EX32(id->id_isar6, ID_ISAR6, SB) != 0;
30
}
31
32
+static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
33
+{
34
+ return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0;
35
+}
36
+
37
static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
38
{
39
/*
40
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_sb(const ARMISARegisters *id)
41
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SB) != 0;
42
}
43
44
+static inline bool isar_feature_aa64_predinv(const ARMISARegisters *id)
45
+{
46
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SPECRES) != 0;
47
+}
48
+
49
static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
50
{
51
/* We always set the AdvSIMD and FP fields identically wrt FP16. */
52
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
20
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
53
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/cpu.c
22
--- a/target/arm/cpu.c
55
+++ b/target/arm/cpu.c
23
+++ b/target/arm/cpu.c
56
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
24
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_initfn(Object *obj)
57
t = FIELD_DP32(t, ID_ISAR6, DP, 1);
25
ARMCPU *cpu = ARM_CPU(obj);
58
t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
26
59
t = FIELD_DP32(t, ID_ISAR6, SB, 1);
27
cpu_set_cpustate_pointers(cpu);
60
+ t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
28
- cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal,
61
cpu->isar.id_isar6 = t;
29
- g_free, cpreg_hashtable_data_destroy);
62
30
+ cpu->cp_regs = g_hash_table_new_full(g_direct_hash, g_direct_equal,
63
t = cpu->id_mmfr4;
31
+ NULL, cpreg_hashtable_data_destroy);
64
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
32
33
QLIST_INIT(&cpu->pre_el_change_hooks);
34
QLIST_INIT(&cpu->el_change_hooks);
35
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
65
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/cpu64.c
37
--- a/target/arm/gdbstub.c
67
+++ b/target/arm/cpu64.c
38
+++ b/target/arm/gdbstub.c
68
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
39
@@ -XXX,XX +XXX,XX @@ static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
69
t = FIELD_DP64(t, ID_AA64ISAR1, GPA, 1);
40
static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
70
t = FIELD_DP64(t, ID_AA64ISAR1, GPI, 0);
41
gpointer p)
71
t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1);
42
{
72
+ t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1);
43
- uint32_t ri_key = *(uint32_t *)key;
73
cpu->isar.id_aa64isar1 = t;
44
+ uint32_t ri_key = (uintptr_t)key;
74
45
ARMCPRegInfo *ri = value;
75
t = cpu->isar.id_aa64pfr0;
46
RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p;
76
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
47
GString *s = param->s;
77
u = FIELD_DP32(u, ID_ISAR6, DP, 1);
78
u = FIELD_DP32(u, ID_ISAR6, FHM, 1);
79
u = FIELD_DP32(u, ID_ISAR6, SB, 1);
80
+ u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1);
81
cpu->isar.id_isar6 = u;
82
83
/*
84
diff --git a/target/arm/helper.c b/target/arm/helper.c
48
diff --git a/target/arm/helper.c b/target/arm/helper.c
85
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
86
--- a/target/arm/helper.c
50
--- a/target/arm/helper.c
87
+++ b/target/arm/helper.c
51
+++ b/target/arm/helper.c
88
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pauth_reginfo[] = {
52
@@ -XXX,XX +XXX,XX @@ bool write_list_to_cpustate(ARMCPU *cpu)
89
};
53
static void add_cpreg_to_list(gpointer key, gpointer opaque)
90
#endif
91
92
+static CPAccessResult access_predinv(CPUARMState *env, const ARMCPRegInfo *ri,
93
+ bool isread)
94
+{
95
+ int el = arm_current_el(env);
96
+
97
+ if (el == 0) {
98
+ uint64_t sctlr = arm_sctlr(env, el);
99
+ if (!(sctlr & SCTLR_EnRCTX)) {
100
+ return CP_ACCESS_TRAP;
101
+ }
102
+ } else if (el == 1) {
103
+ uint64_t hcr = arm_hcr_el2_eff(env);
104
+ if (hcr & HCR_NV) {
105
+ return CP_ACCESS_TRAP_EL2;
106
+ }
107
+ }
108
+ return CP_ACCESS_OK;
109
+}
110
+
111
+static const ARMCPRegInfo predinv_reginfo[] = {
112
+ { .name = "CFP_RCTX", .state = ARM_CP_STATE_AA64,
113
+ .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 3, .opc2 = 4,
114
+ .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
115
+ { .name = "DVP_RCTX", .state = ARM_CP_STATE_AA64,
116
+ .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 3, .opc2 = 5,
117
+ .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
118
+ { .name = "CPP_RCTX", .state = ARM_CP_STATE_AA64,
119
+ .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 3, .opc2 = 7,
120
+ .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
121
+ /*
122
+ * Note the AArch32 opcodes have a different OPC1.
123
+ */
124
+ { .name = "CFPRCTX", .state = ARM_CP_STATE_AA32,
125
+ .cp = 15, .opc1 = 0, .crn = 7, .crm = 3, .opc2 = 4,
126
+ .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
127
+ { .name = "DVPRCTX", .state = ARM_CP_STATE_AA32,
128
+ .cp = 15, .opc1 = 0, .crn = 7, .crm = 3, .opc2 = 5,
129
+ .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
130
+ { .name = "CPPRCTX", .state = ARM_CP_STATE_AA32,
131
+ .cp = 15, .opc1 = 0, .crn = 7, .crm = 3, .opc2 = 7,
132
+ .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
133
+ REGINFO_SENTINEL
134
+};
135
+
136
void register_cp_regs_for_features(ARMCPU *cpu)
137
{
54
{
138
/* Register all the coprocessor registers based on feature bits */
55
ARMCPU *cpu = opaque;
139
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
56
- uint64_t regidx;
140
define_arm_cp_regs(cpu, pauth_reginfo);
57
- const ARMCPRegInfo *ri;
58
-
59
- regidx = *(uint32_t *)key;
60
- ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
61
+ uint32_t regidx = (uintptr_t)key;
62
+ const ARMCPRegInfo *ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
63
64
if (!(ri->type & (ARM_CP_NO_RAW|ARM_CP_ALIAS))) {
65
cpu->cpreg_indexes[cpu->cpreg_array_len] = cpreg_to_kvm_id(regidx);
66
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_list(gpointer key, gpointer opaque)
67
static void count_cpreg(gpointer key, gpointer opaque)
68
{
69
ARMCPU *cpu = opaque;
70
- uint64_t regidx;
71
const ARMCPRegInfo *ri;
72
73
- regidx = *(uint32_t *)key;
74
- ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
75
+ ri = g_hash_table_lookup(cpu->cp_regs, key);
76
77
if (!(ri->type & (ARM_CP_NO_RAW|ARM_CP_ALIAS))) {
78
cpu->cpreg_array_len++;
79
@@ -XXX,XX +XXX,XX @@ static void count_cpreg(gpointer key, gpointer opaque)
80
81
static gint cpreg_key_compare(gconstpointer a, gconstpointer b)
82
{
83
- uint64_t aidx = cpreg_to_kvm_id(*(uint32_t *)a);
84
- uint64_t bidx = cpreg_to_kvm_id(*(uint32_t *)b);
85
+ uint64_t aidx = cpreg_to_kvm_id((uintptr_t)a);
86
+ uint64_t bidx = cpreg_to_kvm_id((uintptr_t)b);
87
88
if (aidx > bidx) {
89
return 1;
90
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
91
for (i = 0; i < ARRAY_SIZE(aliases); i++) {
92
const struct E2HAlias *a = &aliases[i];
93
ARMCPRegInfo *src_reg, *dst_reg, *new_reg;
94
- uint32_t *new_key;
95
bool ok;
96
97
if (a->feature && !a->feature(&cpu->isar)) {
98
continue;
99
}
100
101
- src_reg = g_hash_table_lookup(cpu->cp_regs, &a->src_key);
102
- dst_reg = g_hash_table_lookup(cpu->cp_regs, &a->dst_key);
103
+ src_reg = g_hash_table_lookup(cpu->cp_regs,
104
+ (gpointer)(uintptr_t)a->src_key);
105
+ dst_reg = g_hash_table_lookup(cpu->cp_regs,
106
+ (gpointer)(uintptr_t)a->dst_key);
107
g_assert(src_reg != NULL);
108
g_assert(dst_reg != NULL);
109
110
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
111
112
/* Create alias before redirection so we dup the right data. */
113
new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
114
- new_key = g_memdup(&a->new_key, sizeof(uint32_t));
115
116
new_reg->name = a->new_name;
117
new_reg->type |= ARM_CP_ALIAS;
118
/* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */
119
new_reg->access &= PL2_RW | PL3_RW;
120
121
- ok = g_hash_table_insert(cpu->cp_regs, new_key, new_reg);
122
+ ok = g_hash_table_insert(cpu->cp_regs,
123
+ (gpointer)(uintptr_t)a->new_key, new_reg);
124
g_assert(ok);
125
126
src_reg->opaque = dst_reg;
127
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
128
/* Private utility function for define_one_arm_cp_reg_with_opaque():
129
* add a single reginfo struct to the hash table.
130
*/
131
- uint32_t *key = g_new(uint32_t, 1);
132
+ uint32_t key;
133
ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo));
134
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
135
int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
136
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
137
if (r->cp == 0 || r->state == ARM_CP_STATE_BOTH) {
138
r2->cp = CP_REG_ARM64_SYSREG_CP;
139
}
140
- *key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm,
141
- r2->opc0, opc1, opc2);
142
+ key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm,
143
+ r2->opc0, opc1, opc2);
144
} else {
145
- *key = ENCODE_CP_REG(r2->cp, is64, ns, r2->crn, crm, opc1, opc2);
146
+ key = ENCODE_CP_REG(r2->cp, is64, ns, r2->crn, crm, opc1, opc2);
141
}
147
}
142
#endif
148
if (opaque) {
143
+
149
r2->opaque = opaque;
144
+ /*
150
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
145
+ * While all v8.0 cpus support aarch64, QEMU does have configurations
151
* requested.
146
+ * that do not set ID_AA64ISAR1, e.g. user-only qemu-arm -cpu max,
152
*/
147
+ * which will set ID_ISAR6.
153
if (!(r->type & ARM_CP_OVERRIDE)) {
148
+ */
154
- ARMCPRegInfo *oldreg;
149
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)
155
- oldreg = g_hash_table_lookup(cpu->cp_regs, key);
150
+ ? cpu_isar_feature(aa64_predinv, cpu)
156
+ const ARMCPRegInfo *oldreg = get_arm_cp_reginfo(cpu->cp_regs, key);
151
+ : cpu_isar_feature(aa32_predinv, cpu)) {
157
if (oldreg && !(oldreg->type & ARM_CP_OVERRIDE)) {
152
+ define_arm_cp_regs(cpu, predinv_reginfo);
158
fprintf(stderr, "Register redefined: cp=%d %d bit "
153
+ }
159
"crn=%d crm=%d opc1=%d opc2=%d, "
160
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
161
g_assert_not_reached();
162
}
163
}
164
- g_hash_table_insert(cpu->cp_regs, key, r2);
165
+ g_hash_table_insert(cpu->cp_regs, (gpointer)(uintptr_t)key, r2);
154
}
166
}
155
167
156
void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
168
169
@@ -XXX,XX +XXX,XX @@ void modify_arm_cp_regs_with_len(ARMCPRegInfo *regs, size_t regs_len,
170
171
const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp)
172
{
173
- return g_hash_table_lookup(cpregs, &encoded_cp);
174
+ return g_hash_table_lookup(cpregs, (gpointer)(uintptr_t)encoded_cp);
175
}
176
177
void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
157
--
178
--
158
2.20.1
179
2.25.1
159
160
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Minimize the number of places that will need updating when
3
Simplify freeing cp_regs hash table entries by using a single
4
the virtual host extensions are added.
4
allocation for the entire value.
5
6
This fixes a theoretical bug if we were to ever free the entire
7
hash table, because we've been installing string literal constants
8
into the cpreg structure in define_arm_vh_e2h_redirects_aliases.
9
However, at present we only free entries created for AArch32
10
wildcard cpregs which get overwritten by more specific cpregs,
11
so this bug is never exposed.
5
12
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20190301200501.16533-2-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Message-id: 20220501055028.646596-13-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
17
---
11
target/arm/cpu.h | 26 ++++++++++++++++----------
18
target/arm/cpu.c | 16 +---------------
12
target/arm/helper.c | 8 ++------
19
target/arm/helper.c | 10 ++++++++--
13
2 files changed, 18 insertions(+), 16 deletions(-)
20
2 files changed, 9 insertions(+), 17 deletions(-)
14
21
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
22
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
16
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
24
--- a/target/arm/cpu.c
18
+++ b/target/arm/cpu.h
25
+++ b/target/arm/cpu.c
19
@@ -XXX,XX +XXX,XX @@ static inline bool arm_sctlr_b(CPUARMState *env)
26
@@ -XXX,XX +XXX,XX @@ uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz)
20
(env->cp15.sctlr_el[1] & SCTLR_B) != 0;
27
return (Aff1 << ARM_AFF1_SHIFT) | Aff0;
21
}
28
}
22
29
23
+static inline uint64_t arm_sctlr(CPUARMState *env, int el)
30
-static void cpreg_hashtable_data_destroy(gpointer data)
24
+{
31
-{
25
+ if (el == 0) {
32
- /*
26
+ /* FIXME: ARMv8.1-VHE S2 translation regime. */
33
- * Destroy function for cpu->cp_regs hashtable data entries.
27
+ return env->cp15.sctlr_el[1];
34
- * We must free the name string because it was g_strdup()ed in
28
+ } else {
35
- * add_cpreg_to_hashtable(). It's OK to cast away the 'const'
29
+ return env->cp15.sctlr_el[el];
36
- * from r->name because we know we definitely allocated it.
30
+ }
37
- */
31
+}
38
- ARMCPRegInfo *r = data;
32
+
39
-
33
+
40
- g_free((void *)r->name);
34
/* Return true if the processor is in big-endian mode. */
41
- g_free(r);
35
static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
42
-}
43
-
44
static void arm_cpu_initfn(Object *obj)
36
{
45
{
37
- int cur_el;
46
ARMCPU *cpu = ARM_CPU(obj);
38
-
47
39
/* In 32bit endianness is determined by looking at CPSR's E bit */
48
cpu_set_cpustate_pointers(cpu);
40
if (!is_a64(env)) {
49
cpu->cp_regs = g_hash_table_new_full(g_direct_hash, g_direct_equal,
41
return
50
- NULL, cpreg_hashtable_data_destroy);
42
@@ -XXX,XX +XXX,XX @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
51
+ NULL, g_free);
43
arm_sctlr_b(env) ||
52
44
#endif
53
QLIST_INIT(&cpu->pre_el_change_hooks);
45
((env->uncached_cpsr & CPSR_E) ? 1 : 0);
54
QLIST_INIT(&cpu->el_change_hooks);
46
+ } else {
47
+ int cur_el = arm_current_el(env);
48
+ uint64_t sctlr = arm_sctlr(env, cur_el);
49
+
50
+ return (sctlr & (cur_el ? SCTLR_EE : SCTLR_E0E)) != 0;
51
}
52
-
53
- cur_el = arm_current_el(env);
54
-
55
- if (cur_el == 0) {
56
- return (env->cp15.sctlr_el[1] & SCTLR_E0E) != 0;
57
- }
58
-
59
- return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
60
}
61
62
#include "exec/cpu-all.h"
63
diff --git a/target/arm/helper.c b/target/arm/helper.c
55
diff --git a/target/arm/helper.c b/target/arm/helper.c
64
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/helper.c
57
--- a/target/arm/helper.c
66
+++ b/target/arm/helper.c
58
+++ b/target/arm/helper.c
67
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
59
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
68
flags = FIELD_DP32(flags, TBFLAG_A64, ZCR_LEN, zcr_len);
60
* add a single reginfo struct to the hash table.
69
}
61
*/
70
62
uint32_t key;
71
- if (current_el == 0) {
63
- ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo));
72
- /* FIXME: ARMv8.1-VHE S2 translation regime. */
64
+ ARMCPRegInfo *r2;
73
- sctlr = env->cp15.sctlr_el[1];
65
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
74
- } else {
66
int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
75
- sctlr = env->cp15.sctlr_el[current_el];
67
+ size_t name_len;
76
- }
77
+ sctlr = arm_sctlr(env, current_el);
78
+
68
+
79
if (cpu_isar_feature(aa64_pauth, cpu)) {
69
+ /* Combine cpreg and name into one allocation. */
80
/*
70
+ name_len = strlen(name) + 1;
81
* In order to save space in flags, we record only whether
71
+ r2 = g_malloc(sizeof(*r2) + name_len);
72
+ *r2 = *r;
73
+ r2->name = memcpy(r2 + 1, name, name_len);
74
75
- r2->name = g_strdup(name);
76
/* Reset the secure state to the specific incoming state. This is
77
* necessary as the register may have been defined with both states.
78
*/
82
--
79
--
83
2.20.1
80
2.25.1
84
85
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We are about to allow the memory map to grow beyond 1TB and
3
Move the computation of key to the top of the function.
4
potentially overshoot the VCPU AA64MMFR0.PARANGE.
4
Hoist the resolution of cp as well, as an input to the
5
computation of key.
5
6
6
In aarch64 mode and when highmem is set, let's check the VCPU
7
This will be required by a subsequent patch.
7
PA range is sufficient to address the highest GPA of the memory
8
map.
9
8
10
Signed-off-by: Eric Auger <eric.auger@redhat.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20190304101339.25970-10-eric.auger@redhat.com
11
Message-id: 20220501055028.646596-14-richard.henderson@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/virt.c | 17 +++++++++++++++++
14
target/arm/helper.c | 49 +++++++++++++++++++++++++--------------------
16
1 file changed, 17 insertions(+)
15
1 file changed, 27 insertions(+), 22 deletions(-)
17
16
18
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/virt.c
19
--- a/target/arm/helper.c
21
+++ b/hw/arm/virt.c
20
+++ b/target/arm/helper.c
22
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
23
#include "standard-headers/linux/input.h"
22
ARMCPRegInfo *r2;
24
#include "hw/arm/smmuv3.h"
23
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
25
#include "hw/acpi/acpi.h"
24
int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
26
+#include "target/arm/internals.h"
25
+ int cp = r->cp;
27
26
size_t name_len;
28
#define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
27
29
static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
28
+ switch (state) {
30
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
29
+ case ARM_CP_STATE_AA32:
31
fdt_add_timer_nodes(vms);
30
+ /* We assume it is a cp15 register if the .cp field is left unset. */
32
fdt_add_cpu_nodes(vms);
31
+ if (cp == 0 && r->state == ARM_CP_STATE_BOTH) {
33
32
+ cp = 15;
34
+ if (!kvm_enabled()) {
35
+ ARMCPU *cpu = ARM_CPU(first_cpu);
36
+ bool aarch64 = object_property_get_bool(OBJECT(cpu), "aarch64", NULL);
37
+
38
+ if (aarch64 && vms->highmem) {
39
+ int requested_pa_size, pamax = arm_pamax(cpu);
40
+
41
+ requested_pa_size = 64 - clz64(vms->highest_gpa);
42
+ if (pamax < requested_pa_size) {
43
+ error_report("VCPU supports less PA bits (%d) than requested "
44
+ "by the memory map (%d)", pamax, requested_pa_size);
45
+ exit(1);
46
+ }
47
+ }
33
+ }
34
+ key = ENCODE_CP_REG(cp, is64, ns, r->crn, crm, opc1, opc2);
35
+ break;
36
+ case ARM_CP_STATE_AA64:
37
+ /*
38
+ * To allow abbreviation of ARMCPRegInfo definitions, we treat
39
+ * cp == 0 as equivalent to the value for "standard guest-visible
40
+ * sysreg". STATE_BOTH definitions are also always "standard sysreg"
41
+ * in their AArch64 view (the .cp value may be non-zero for the
42
+ * benefit of the AArch32 view).
43
+ */
44
+ if (cp == 0 || r->state == ARM_CP_STATE_BOTH) {
45
+ cp = CP_REG_ARM64_SYSREG_CP;
46
+ }
47
+ key = ENCODE_AA64_CP_REG(cp, r->crn, crm, r->opc0, opc1, opc2);
48
+ break;
49
+ default:
50
+ g_assert_not_reached();
48
+ }
51
+ }
49
+
52
+
50
memory_region_allocate_system_memory(ram, NULL, "mach-virt.ram",
53
/* Combine cpreg and name into one allocation. */
51
machine->ram_size);
54
name_len = strlen(name) + 1;
52
memory_region_add_subregion(sysmem, vms->memmap[VIRT_MEM].base, ram);
55
r2 = g_malloc(sizeof(*r2) + name_len);
56
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
57
}
58
59
if (r->state == ARM_CP_STATE_BOTH) {
60
- /* We assume it is a cp15 register if the .cp field is left unset.
61
- */
62
- if (r2->cp == 0) {
63
- r2->cp = 15;
64
- }
65
-
66
#if HOST_BIG_ENDIAN
67
if (r2->fieldoffset) {
68
r2->fieldoffset += sizeof(uint32_t);
69
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
70
#endif
71
}
72
}
73
- if (state == ARM_CP_STATE_AA64) {
74
- /* To allow abbreviation of ARMCPRegInfo
75
- * definitions, we treat cp == 0 as equivalent to
76
- * the value for "standard guest-visible sysreg".
77
- * STATE_BOTH definitions are also always "standard
78
- * sysreg" in their AArch64 view (the .cp value may
79
- * be non-zero for the benefit of the AArch32 view).
80
- */
81
- if (r->cp == 0 || r->state == ARM_CP_STATE_BOTH) {
82
- r2->cp = CP_REG_ARM64_SYSREG_CP;
83
- }
84
- key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm,
85
- r2->opc0, opc1, opc2);
86
- } else {
87
- key = ENCODE_CP_REG(r2->cp, is64, ns, r2->crn, crm, opc1, opc2);
88
- }
89
if (opaque) {
90
r2->opaque = opaque;
91
}
92
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
93
/* Make sure reginfo passed to helpers for wildcarded regs
94
* has the correct crm/opc1/opc2 for this reg, not CP_ANY:
95
*/
96
+ r2->cp = cp;
97
r2->crm = crm;
98
r2->opc1 = opc1;
99
r2->opc2 = opc2;
53
--
100
--
54
2.20.1
101
2.25.1
55
56
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This patch implements the machine class kvm_type() callback.
3
Put most of the value writeback to the same place,
4
It returns the number of bits requested to implement the whole GPA
4
and improve the comment that goes with them.
5
range including the RAM and IO regions located beyond.
6
The returned value is passed though the KVM_CREATE_VM ioctl and
7
this allows KVM to set the stage2 tables dynamically.
8
5
9
To compute the highest GPA used in the memory map, kvm_type()
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
must freeze the memory map by calling virt_set_memmap().
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
8
Message-id: 20220501055028.646596-15-richard.henderson@linaro.org
12
Signed-off-by: Eric Auger <eric.auger@redhat.com>
13
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
14
Message-id: 20190304101339.25970-9-eric.auger@redhat.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
10
---
17
hw/arm/virt.c | 39 ++++++++++++++++++++++++++++++++++++++-
11
target/arm/helper.c | 28 ++++++++++++----------------
18
1 file changed, 38 insertions(+), 1 deletion(-)
12
1 file changed, 12 insertions(+), 16 deletions(-)
19
13
20
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/virt.c
16
--- a/target/arm/helper.c
23
+++ b/hw/arm/virt.c
17
+++ b/target/arm/helper.c
24
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
18
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
25
bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
19
*r2 = *r;
26
bool aarch64 = true;
20
r2->name = memcpy(r2 + 1, name, name_len);
27
21
28
- virt_set_memmap(vms);
22
- /* Reset the secure state to the specific incoming state. This is
23
- * necessary as the register may have been defined with both states.
29
+ /*
24
+ /*
30
+ * In accelerated mode, the memory map is computed earlier in kvm_type()
25
+ * Update fields to match the instantiation, overwiting wildcards
31
+ * to create a VM with the right number of IPA bits.
26
+ * such as CP_ANY, ARM_CP_STATE_BOTH, or ARM_CP_SECSTATE_BOTH.
32
+ */
27
*/
33
+ if (!vms->memmap) {
28
+ r2->cp = cp;
34
+ virt_set_memmap(vms);
29
+ r2->crm = crm;
30
+ r2->opc1 = opc1;
31
+ r2->opc2 = opc2;
32
+ r2->state = state;
33
r2->secure = secstate;
34
+ if (opaque) {
35
+ r2->opaque = opaque;
35
+ }
36
+ }
36
37
37
/* We can probe only here because during property set
38
if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
38
* KVM is not available yet
39
/* Register is banked (using both entries in array).
39
@@ -XXX,XX +XXX,XX @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
40
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
40
return NULL;
41
#endif
41
}
42
}
42
43
}
43
+/*
44
- if (opaque) {
44
+ * for arm64 kvm_type [7-0] encodes the requested number of bits
45
- r2->opaque = opaque;
45
+ * in the IPA address space
46
- }
46
+ */
47
- /* reginfo passed to helpers is correct for the actual access,
47
+static int virt_kvm_type(MachineState *ms, const char *type_str)
48
- * and is never ARM_CP_STATE_BOTH:
48
+{
49
- */
49
+ VirtMachineState *vms = VIRT_MACHINE(ms);
50
- r2->state = state;
50
+ int max_vm_pa_size = kvm_arm_get_max_vm_ipa_size(ms);
51
- /* Make sure reginfo passed to helpers for wildcarded regs
51
+ int requested_pa_size;
52
- * has the correct crm/opc1/opc2 for this reg, not CP_ANY:
53
- */
54
- r2->cp = cp;
55
- r2->crm = crm;
56
- r2->opc1 = opc1;
57
- r2->opc2 = opc2;
52
+
58
+
53
+ /* we freeze the memory map to compute the highest gpa */
59
/* By convention, for wildcarded registers only the first
54
+ virt_set_memmap(vms);
60
* entry is used for migration; the others are marked as
55
+
61
* ALIAS so we don't try to transfer the register
56
+ requested_pa_size = 64 - clz64(vms->highest_gpa);
57
+
58
+ if (requested_pa_size > max_vm_pa_size) {
59
+ error_report("-m and ,maxmem option values "
60
+ "require an IPA range (%d bits) larger than "
61
+ "the one supported by the host (%d bits)",
62
+ requested_pa_size, max_vm_pa_size);
63
+ exit(1);
64
+ }
65
+ /*
66
+ * By default we return 0 which corresponds to an implicit legacy
67
+ * 40b IPA setting. Otherwise we return the actual requested PA
68
+ * logsize
69
+ */
70
+ return requested_pa_size > 40 ? requested_pa_size : 0;
71
+}
72
+
73
static void virt_machine_class_init(ObjectClass *oc, void *data)
74
{
75
MachineClass *mc = MACHINE_CLASS(oc);
76
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
77
mc->cpu_index_to_instance_props = virt_cpu_index_to_props;
78
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
79
mc->get_default_cpu_node_id = virt_get_default_cpu_node_id;
80
+ mc->kvm_type = virt_kvm_type;
81
assert(!mc->get_hotplug_handler);
82
mc->get_hotplug_handler = virt_machine_get_hotplug_handler;
83
hc->plug = virt_machine_device_plug_cb;
84
--
62
--
85
2.20.1
63
2.25.1
86
87
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Up to now the memory map has been static and the high IO region
3
Bool is a more appropriate type for these variables.
4
base has always been 256GiB.
5
4
6
This patch modifies the virt_set_memmap() function, which freezes
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
the memory map, so that the high IO range base becomes floating,
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
located after the initial RAM and the device memory.
7
Message-id: 20220501055028.646596-16-richard.henderson@linaro.org
9
10
The function computes
11
- the base of the device memory,
12
- the size of the device memory,
13
- the high IO region base
14
- the highest GPA used in the memory map.
15
16
Entries of the high IO region are assigned a base address. The
17
device memory is initialized.
18
19
The highest GPA used in the memory map will be used at VM creation
20
to choose the requested IPA size.
21
22
Setting all the existing highmem IO regions beyond the RAM
23
allows to have a single contiguous RAM region (initial RAM and
24
possible hotpluggable device memory). That way we do not need
25
to do invasive changes in the EDK2 FW to support a dynamic
26
RAM base.
27
28
Still the user cannot request an initial RAM size greater than 255GB.
29
30
Signed-off-by: Eric Auger <eric.auger@redhat.com>
31
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
32
Message-id: 20190304101339.25970-8-eric.auger@redhat.com
33
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
34
---
9
---
35
include/hw/arm/virt.h | 1 +
10
target/arm/helper.c | 4 ++--
36
hw/arm/virt.c | 52 ++++++++++++++++++++++++++++++++++++++-----
11
1 file changed, 2 insertions(+), 2 deletions(-)
37
2 files changed, 47 insertions(+), 6 deletions(-)
38
12
39
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
40
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
41
--- a/include/hw/arm/virt.h
15
--- a/target/arm/helper.c
42
+++ b/include/hw/arm/virt.h
16
+++ b/target/arm/helper.c
43
@@ -XXX,XX +XXX,XX @@ typedef struct {
17
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
44
uint32_t msi_phandle;
18
*/
45
uint32_t iommu_phandle;
19
uint32_t key;
46
int psci_conduit;
20
ARMCPRegInfo *r2;
47
+ hwaddr highest_gpa;
21
- int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
48
} VirtMachineState;
22
- int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
49
23
+ bool is64 = r->type & ARM_CP_64BIT;
50
#define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)
24
+ bool ns = secstate & ARM_CP_SECSTATE_NS;
51
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
25
int cp = r->cp;
52
index XXXXXXX..XXXXXXX 100644
26
size_t name_len;
53
--- a/hw/arm/virt.c
54
+++ b/hw/arm/virt.c
55
@@ -XXX,XX +XXX,XX @@
56
#include "qapi/visitor.h"
57
#include "standard-headers/linux/input.h"
58
#include "hw/arm/smmuv3.h"
59
+#include "hw/acpi/acpi.h"
60
61
#define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
62
static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
63
@@ -XXX,XX +XXX,XX @@
64
* of a terabyte of RAM will be doing it on a host with more than a
65
* terabyte of physical address space.)
66
*/
67
-#define RAMLIMIT_GB 255
68
-#define RAMLIMIT_BYTES (RAMLIMIT_GB * 1024ULL * 1024 * 1024)
69
+#define LEGACY_RAMLIMIT_GB 255
70
+#define LEGACY_RAMLIMIT_BYTES (LEGACY_RAMLIMIT_GB * GiB)
71
72
/* Addresses and sizes of our components.
73
* 0..128MB is space for a flash device so we can run bootrom code such as UEFI.
74
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry base_memmap[] = {
75
[VIRT_PCIE_MMIO] = { 0x10000000, 0x2eff0000 },
76
[VIRT_PCIE_PIO] = { 0x3eff0000, 0x00010000 },
77
[VIRT_PCIE_ECAM] = { 0x3f000000, 0x01000000 },
78
- [VIRT_MEM] = { 0x40000000, RAMLIMIT_BYTES },
79
+ /* Actual RAM size depends on initial RAM and device memory settings */
80
+ [VIRT_MEM] = { GiB, LEGACY_RAMLIMIT_BYTES },
81
};
82
83
/*
84
@@ -XXX,XX +XXX,XX @@ static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx)
85
86
static void virt_set_memmap(VirtMachineState *vms)
87
{
88
- hwaddr base;
89
+ MachineState *ms = MACHINE(vms);
90
+ hwaddr base, device_memory_base, device_memory_size;
91
int i;
92
93
vms->memmap = extended_memmap;
94
@@ -XXX,XX +XXX,XX @@ static void virt_set_memmap(VirtMachineState *vms)
95
vms->memmap[i] = base_memmap[i];
96
}
97
98
- base = 256 * GiB; /* Top of the legacy initial RAM region */
99
+ if (ms->ram_slots > ACPI_MAX_RAM_SLOTS) {
100
+ error_report("unsupported number of memory slots: %"PRIu64,
101
+ ms->ram_slots);
102
+ exit(EXIT_FAILURE);
103
+ }
104
+
105
+ /*
106
+ * We compute the base of the high IO region depending on the
107
+ * amount of initial and device memory. The device memory start/size
108
+ * is aligned on 1GiB. We never put the high IO region below 256GiB
109
+ * so that if maxram_size is < 255GiB we keep the legacy memory map.
110
+ * The device region size assumes 1GiB page max alignment per slot.
111
+ */
112
+ device_memory_base =
113
+ ROUND_UP(vms->memmap[VIRT_MEM].base + ms->ram_size, GiB);
114
+ device_memory_size = ms->maxram_size - ms->ram_size + ms->ram_slots * GiB;
115
+
116
+ /* Base address of the high IO region */
117
+ base = device_memory_base + ROUND_UP(device_memory_size, GiB);
118
+ if (base < device_memory_base) {
119
+ error_report("maxmem/slots too huge");
120
+ exit(EXIT_FAILURE);
121
+ }
122
+ if (base < vms->memmap[VIRT_MEM].base + LEGACY_RAMLIMIT_BYTES) {
123
+ base = vms->memmap[VIRT_MEM].base + LEGACY_RAMLIMIT_BYTES;
124
+ }
125
126
for (i = VIRT_LOWMEMMAP_LAST; i < ARRAY_SIZE(extended_memmap); i++) {
127
hwaddr size = extended_memmap[i].size;
128
@@ -XXX,XX +XXX,XX @@ static void virt_set_memmap(VirtMachineState *vms)
129
vms->memmap[i].size = size;
130
base += size;
131
}
132
+ vms->highest_gpa = base - 1;
133
+ if (device_memory_size > 0) {
134
+ ms->device_memory = g_malloc0(sizeof(*ms->device_memory));
135
+ ms->device_memory->base = device_memory_base;
136
+ memory_region_init(&ms->device_memory->mr, OBJECT(vms),
137
+ "device-memory", device_memory_size);
138
+ }
139
}
140
141
static void machvirt_init(MachineState *machine)
142
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
143
vms->smp_cpus = smp_cpus;
144
145
if (machine->ram_size > vms->memmap[VIRT_MEM].size) {
146
- error_report("mach-virt: cannot model more than %dGB RAM", RAMLIMIT_GB);
147
+ error_report("mach-virt: cannot model more than %dGB RAM",
148
+ LEGACY_RAMLIMIT_GB);
149
exit(1);
150
}
151
152
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
153
memory_region_allocate_system_memory(ram, NULL, "mach-virt.ram",
154
machine->ram_size);
155
memory_region_add_subregion(sysmem, vms->memmap[VIRT_MEM].base, ram);
156
+ if (machine->device_memory) {
157
+ memory_region_add_subregion(sysmem, machine->device_memory->base,
158
+ &machine->device_memory->mr);
159
+ }
160
161
create_flash(vms, sysmem, secure_sysmem ? secure_sysmem : sysmem);
162
27
163
--
28
--
164
2.20.1
29
2.25.1
165
166
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Found by inspection: Rn is the base register against which the
3
Computing isbanked only once makes the code
4
load began; I is the register within the mask being processed.
4
a bit easier to read.
5
The exception return should of course be processed from the loaded PC.
6
5
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20190301202921.21209-1-richard.henderson@linaro.org
8
Message-id: 20220501055028.646596-17-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
target/arm/translate.c | 2 +-
11
target/arm/helper.c | 6 ++++--
13
1 file changed, 1 insertion(+), 1 deletion(-)
12
1 file changed, 4 insertions(+), 2 deletions(-)
14
13
15
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate.c
16
--- a/target/arm/helper.c
18
+++ b/target/arm/translate.c
17
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
18
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
20
} else if (i == rn) {
19
bool is64 = r->type & ARM_CP_64BIT;
21
loaded_var = tmp;
20
bool ns = secstate & ARM_CP_SECSTATE_NS;
22
loaded_base = 1;
21
int cp = r->cp;
23
- } else if (rn == 15 && exc_return) {
22
+ bool isbanked;
24
+ } else if (i == 15 && exc_return) {
23
size_t name_len;
25
store_pc_exc_ret(s, tmp);
24
26
} else {
25
switch (state) {
27
store_reg_from_load(s, i, tmp);
26
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
27
r2->opaque = opaque;
28
}
29
30
- if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
31
+ isbanked = r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1];
32
+ if (isbanked) {
33
/* Register is banked (using both entries in array).
34
* Overwriting fieldoffset as the array is only used to define
35
* banked registers but later only fieldoffset is used.
36
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
37
}
38
39
if (state == ARM_CP_STATE_AA32) {
40
- if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
41
+ if (isbanked) {
42
/* If the register is banked then we don't need to migrate or
43
* reset the 32-bit instance in certain cases:
44
*
28
--
45
--
29
2.20.1
46
2.25.1
30
31
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
In the prospect to introduce an extended memory map supporting more
3
Perform the override check early, so that it is still done
4
RAM, let's split the memory map array into two parts:
4
even when we decide to discard an unreachable cpreg.
5
5
6
- the former a15memmap, renamed base_memmap, contains regions below
6
Use assert not printf+abort.
7
and including the RAM. MemMapEntries initialized in this array
8
have a static size and base address.
9
- extended_memmap, only initialized with entries located after the
10
RAM. MemMapEntries initialized in this array only get their size
11
initialized. Their base address is dynamically computed depending
12
on the the top of the RAM, with same alignment as their size.
13
7
14
Eventually base_memmap entries are copied into the extended_memmap
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
array. Using two separate arrays however clarifies which entries
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
are statically allocated and those which are dynamically allocated.
10
Message-id: 20220501055028.646596-18-richard.henderson@linaro.org
17
18
This new split will allow to grow the RAM size without changing the
19
description of the high IO entries.
20
21
We introduce a new virt_set_memmap() helper function which
22
"freezes" the memory map. We call it in machvirt_init as
23
memory attributes of the machine are not yet set when
24
virt_instance_init() gets called.
25
26
The memory map is unchanged (the top of the initial RAM still is
27
256GiB). Then come the high IO regions with same layout as before.
28
29
Signed-off-by: Eric Auger <eric.auger@redhat.com>
30
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
31
Message-id: 20190304101339.25970-4-eric.auger@redhat.com
32
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
33
---
12
---
34
include/hw/arm/virt.h | 13 +++++++----
13
target/arm/helper.c | 22 ++++++++--------------
35
hw/arm/virt.c | 50 +++++++++++++++++++++++++++++++++++++------
14
1 file changed, 8 insertions(+), 14 deletions(-)
36
2 files changed, 53 insertions(+), 10 deletions(-)
37
15
38
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
39
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
40
--- a/include/hw/arm/virt.h
18
--- a/target/arm/helper.c
41
+++ b/include/hw/arm/virt.h
19
+++ b/target/arm/helper.c
42
@@ -XXX,XX +XXX,XX @@ enum {
20
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
43
VIRT_GIC_VCPU,
21
g_assert_not_reached();
44
VIRT_GIC_ITS,
22
}
45
VIRT_GIC_REDIST,
23
46
- VIRT_HIGH_GIC_REDIST2,
24
+ /* Overriding of an existing definition must be explicitly requested. */
47
VIRT_SMMU,
25
+ if (!(r->type & ARM_CP_OVERRIDE)) {
48
VIRT_UART,
26
+ const ARMCPRegInfo *oldreg = get_arm_cp_reginfo(cpu->cp_regs, key);
49
VIRT_MMIO,
27
+ if (oldreg) {
50
@@ -XXX,XX +XXX,XX @@ enum {
28
+ assert(oldreg->type & ARM_CP_OVERRIDE);
51
VIRT_PCIE_MMIO,
29
+ }
52
VIRT_PCIE_PIO,
53
VIRT_PCIE_ECAM,
54
- VIRT_HIGH_PCIE_ECAM,
55
VIRT_PLATFORM_BUS,
56
- VIRT_HIGH_PCIE_MMIO,
57
VIRT_GPIO,
58
VIRT_SECURE_UART,
59
VIRT_SECURE_MEM,
60
+ VIRT_LOWMEMMAP_LAST,
61
+};
62
+
63
+/* indices of IO regions located after the RAM */
64
+enum {
65
+ VIRT_HIGH_GIC_REDIST2 = VIRT_LOWMEMMAP_LAST,
66
+ VIRT_HIGH_PCIE_ECAM,
67
+ VIRT_HIGH_PCIE_MMIO,
68
};
69
70
typedef enum VirtIOMMUType {
71
@@ -XXX,XX +XXX,XX @@ typedef struct {
72
int32_t gic_version;
73
VirtIOMMUType iommu;
74
struct arm_boot_info bootinfo;
75
- const MemMapEntry *memmap;
76
+ MemMapEntry *memmap;
77
const int *irqmap;
78
int smp_cpus;
79
void *fdt;
80
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/hw/arm/virt.c
83
+++ b/hw/arm/virt.c
84
@@ -XXX,XX +XXX,XX @@
85
*/
86
87
#include "qemu/osdep.h"
88
+#include "qemu/units.h"
89
#include "qapi/error.h"
90
#include "hw/sysbus.h"
91
#include "hw/arm/arm.h"
92
@@ -XXX,XX +XXX,XX @@
93
* Note that devices should generally be placed at multiples of 0x10000,
94
* to accommodate guests using 64K pages.
95
*/
96
-static const MemMapEntry a15memmap[] = {
97
+static const MemMapEntry base_memmap[] = {
98
/* Space up to 0x8000000 is reserved for a boot ROM */
99
[VIRT_FLASH] = { 0, 0x08000000 },
100
[VIRT_CPUPERIPHS] = { 0x08000000, 0x00020000 },
101
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry a15memmap[] = {
102
[VIRT_PCIE_PIO] = { 0x3eff0000, 0x00010000 },
103
[VIRT_PCIE_ECAM] = { 0x3f000000, 0x01000000 },
104
[VIRT_MEM] = { 0x40000000, RAMLIMIT_BYTES },
105
+};
106
+
107
+/*
108
+ * Highmem IO Regions: This memory map is floating, located after the RAM.
109
+ * Each MemMapEntry base (GPA) will be dynamically computed, depending on the
110
+ * top of the RAM, so that its base get the same alignment as the size,
111
+ * ie. a 512GiB entry will be aligned on a 512GiB boundary. If there is
112
+ * less than 256GiB of RAM, the floating area starts at the 256GiB mark.
113
+ * Note the extended_memmap is sized so that it eventually also includes the
114
+ * base_memmap entries (VIRT_HIGH_GIC_REDIST2 index is greater than the last
115
+ * index of base_memmap).
116
+ */
117
+static MemMapEntry extended_memmap[] = {
118
/* Additional 64 MB redist region (can contain up to 512 redistributors) */
119
- [VIRT_HIGH_GIC_REDIST2] = { 0x4000000000ULL, 0x4000000 },
120
- [VIRT_HIGH_PCIE_ECAM] = { 0x4010000000ULL, 0x10000000 },
121
- /* Second PCIe window, 512GB wide at the 512GB boundary */
122
- [VIRT_HIGH_PCIE_MMIO] = { 0x8000000000ULL, 0x8000000000ULL },
123
+ [VIRT_HIGH_GIC_REDIST2] = { 0x0, 64 * MiB },
124
+ [VIRT_HIGH_PCIE_ECAM] = { 0x0, 256 * MiB },
125
+ /* Second PCIe window */
126
+ [VIRT_HIGH_PCIE_MMIO] = { 0x0, 512 * GiB },
127
};
128
129
static const int a15irqmap[] = {
130
@@ -XXX,XX +XXX,XX @@ static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx)
131
return arm_cpu_mp_affinity(idx, clustersz);
132
}
133
134
+static void virt_set_memmap(VirtMachineState *vms)
135
+{
136
+ hwaddr base;
137
+ int i;
138
+
139
+ vms->memmap = extended_memmap;
140
+
141
+ for (i = 0; i < ARRAY_SIZE(base_memmap); i++) {
142
+ vms->memmap[i] = base_memmap[i];
143
+ }
30
+ }
144
+
31
+
145
+ base = 256 * GiB; /* Top of the legacy initial RAM region */
32
/* Combine cpreg and name into one allocation. */
146
+
33
name_len = strlen(name) + 1;
147
+ for (i = VIRT_LOWMEMMAP_LAST; i < ARRAY_SIZE(extended_memmap); i++) {
34
r2 = g_malloc(sizeof(*r2) + name_len);
148
+ hwaddr size = extended_memmap[i].size;
35
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
149
+
36
assert(!raw_accessors_invalid(r2));
150
+ base = ROUND_UP(base, size);
37
}
151
+ vms->memmap[i].base = base;
38
152
+ vms->memmap[i].size = size;
39
- /* Overriding of an existing definition must be explicitly
153
+ base += size;
40
- * requested.
154
+ }
41
- */
155
+}
42
- if (!(r->type & ARM_CP_OVERRIDE)) {
156
+
43
- const ARMCPRegInfo *oldreg = get_arm_cp_reginfo(cpu->cp_regs, key);
157
static void machvirt_init(MachineState *machine)
44
- if (oldreg && !(oldreg->type & ARM_CP_OVERRIDE)) {
158
{
45
- fprintf(stderr, "Register redefined: cp=%d %d bit "
159
VirtMachineState *vms = VIRT_MACHINE(machine);
46
- "crn=%d crm=%d opc1=%d opc2=%d, "
160
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
47
- "was %s, now %s\n", r2->cp, 32 + 32 * is64,
161
bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
48
- r2->crn, r2->crm, r2->opc1, r2->opc2,
162
bool aarch64 = true;
49
- oldreg->name, r2->name);
163
50
- g_assert_not_reached();
164
+ virt_set_memmap(vms);
51
- }
165
+
52
- }
166
/* We can probe only here because during property set
53
g_hash_table_insert(cpu->cp_regs, (gpointer)(uintptr_t)key, r2);
167
* KVM is not available yet
168
*/
169
@@ -XXX,XX +XXX,XX @@ static void virt_instance_init(Object *obj)
170
"Valid values are none and smmuv3",
171
NULL);
172
173
- vms->memmap = a15memmap;
174
vms->irqmap = a15irqmap;
175
}
54
}
176
55
177
--
56
--
178
2.20.1
57
2.25.1
179
180
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This decoding more closely matches the ARMv8.4 Table C4-6,
3
Put the block comments into the current coding style.
4
Encoding table for Data Processing - Register Group.
5
6
In particular, op2 == 0 is now more than just Add/sub (with carry).
7
4
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20190301200501.16533-7-richard.henderson@linaro.org
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20220501055028.646596-19-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
9
---
13
target/arm/translate-a64.c | 98 ++++++++++++++++++++++----------------
10
target/arm/helper.c | 24 +++++++++++++++---------
14
1 file changed, 57 insertions(+), 41 deletions(-)
11
1 file changed, 15 insertions(+), 9 deletions(-)
15
12
16
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate-a64.c
15
--- a/target/arm/helper.c
19
+++ b/target/arm/translate-a64.c
16
+++ b/target/arm/helper.c
20
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
17
@@ -XXX,XX +XXX,XX @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
18
return cpu_list;
21
}
19
}
22
20
23
/* Add/subtract (with carry)
21
+/*
24
- * 31 30 29 28 27 26 25 24 23 22 21 20 16 15 10 9 5 4 0
22
+ * Private utility function for define_one_arm_cp_reg_with_opaque():
25
- * +--+--+--+------------------------+------+---------+------+-----+
23
+ * add a single reginfo struct to the hash table.
26
- * |sf|op| S| 1 1 0 1 0 0 0 0 | rm | opcode2 | Rn | Rd |
24
+ */
27
- * +--+--+--+------------------------+------+---------+------+-----+
25
static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
28
- * [000000]
26
void *opaque, CPState state,
29
+ * 31 30 29 28 27 26 25 24 23 22 21 20 16 15 10 9 5 4 0
27
CPSecureState secstate,
30
+ * +--+--+--+------------------------+------+-------------+------+-----+
28
int crm, int opc1, int opc2,
31
+ * |sf|op| S| 1 1 0 1 0 0 0 0 | rm | 0 0 0 0 0 0 | Rn | Rd |
29
const char *name)
32
+ * +--+--+--+------------------------+------+-------------+------+-----+
30
{
33
*/
31
- /* Private utility function for define_one_arm_cp_reg_with_opaque():
34
32
- * add a single reginfo struct to the hash table.
35
static void disas_adc_sbc(DisasContext *s, uint32_t insn)
33
- */
36
@@ -XXX,XX +XXX,XX @@ static void disas_adc_sbc(DisasContext *s, uint32_t insn)
34
uint32_t key;
37
unsigned int sf, op, setflags, rm, rn, rd;
35
ARMCPRegInfo *r2;
38
TCGv_i64 tcg_y, tcg_rn, tcg_rd;
36
bool is64 = r->type & ARM_CP_64BIT;
39
37
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
40
- if (extract32(insn, 10, 6) != 0) {
38
41
- unallocated_encoding(s);
39
isbanked = r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1];
42
- return;
40
if (isbanked) {
43
- }
41
- /* Register is banked (using both entries in array).
44
-
42
+ /*
45
sf = extract32(insn, 31, 1);
43
+ * Register is banked (using both entries in array).
46
op = extract32(insn, 30, 1);
44
* Overwriting fieldoffset as the array is only used to define
47
setflags = extract32(insn, 29, 1);
45
* banked registers but later only fieldoffset is used.
48
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
46
*/
47
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
48
49
if (state == ARM_CP_STATE_AA32) {
50
if (isbanked) {
51
- /* If the register is banked then we don't need to migrate or
52
+ /*
53
+ * If the register is banked then we don't need to migrate or
54
* reset the 32-bit instance in certain cases:
55
*
56
* 1) If the register has both 32-bit and 64-bit instances then we
57
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
58
r2->type |= ARM_CP_ALIAS;
59
}
60
} else if ((secstate != r->secure) && !ns) {
61
- /* The register is not banked so we only want to allow migration of
62
- * the non-secure instance.
63
+ /*
64
+ * The register is not banked so we only want to allow migration
65
+ * of the non-secure instance.
66
*/
67
r2->type |= ARM_CP_ALIAS;
68
}
69
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
70
}
49
}
71
}
50
}
72
51
73
- /* By convention, for wildcarded registers only the first
52
-/* Data processing - register */
74
+ /*
53
+/*
75
+ * By convention, for wildcarded registers only the first
54
+ * Data processing - register
76
* entry is used for migration; the others are marked as
55
+ * 31 30 29 28 25 21 20 16 10 0
77
* ALIAS so we don't try to transfer the register
56
+ * +--+---+--+---+-------+-----+-------+-------+---------+
78
* multiple times. Special registers (ie NOP/WFI) are
57
+ * | |op0| |op1| 1 0 1 | op2 | | op3 | |
79
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
58
+ * +--+---+--+---+-------+-----+-------+-------+---------+
80
r2->type |= ARM_CP_ALIAS | ARM_CP_NO_GDB;
59
+ */
60
static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
61
{
62
- switch (extract32(insn, 24, 5)) {
63
- case 0x0a: /* Logical (shifted register) */
64
- disas_logic_reg(s, insn);
65
- break;
66
- case 0x0b: /* Add/subtract */
67
- if (insn & (1 << 21)) { /* (extended register) */
68
- disas_add_sub_ext_reg(s, insn);
69
+ int op0 = extract32(insn, 30, 1);
70
+ int op1 = extract32(insn, 28, 1);
71
+ int op2 = extract32(insn, 21, 4);
72
+ int op3 = extract32(insn, 10, 6);
73
+
74
+ if (!op1) {
75
+ if (op2 & 8) {
76
+ if (op2 & 1) {
77
+ /* Add/sub (extended register) */
78
+ disas_add_sub_ext_reg(s, insn);
79
+ } else {
80
+ /* Add/sub (shifted register) */
81
+ disas_add_sub_reg(s, insn);
82
+ }
83
} else {
84
- disas_add_sub_reg(s, insn);
85
+ /* Logical (shifted register) */
86
+ disas_logic_reg(s, insn);
87
}
88
- break;
89
- case 0x1b: /* Data-processing (3 source) */
90
- disas_data_proc_3src(s, insn);
91
- break;
92
- case 0x1a:
93
- switch (extract32(insn, 21, 3)) {
94
- case 0x0: /* Add/subtract (with carry) */
95
+ return;
96
+ }
97
+
98
+ switch (op2) {
99
+ case 0x0:
100
+ switch (op3) {
101
+ case 0x00: /* Add/subtract (with carry) */
102
disas_adc_sbc(s, insn);
103
break;
104
- case 0x2: /* Conditional compare */
105
- disas_cc(s, insn); /* both imm and reg forms */
106
- break;
107
- case 0x4: /* Conditional select */
108
- disas_cond_select(s, insn);
109
- break;
110
- case 0x6: /* Data-processing */
111
- if (insn & (1 << 30)) { /* (1 source) */
112
- disas_data_proc_1src(s, insn);
113
- } else { /* (2 source) */
114
- disas_data_proc_2src(s, insn);
115
- }
116
- break;
117
+
118
default:
119
- unallocated_encoding(s);
120
- break;
121
+ goto do_unallocated;
122
}
123
break;
124
+
125
+ case 0x2: /* Conditional compare */
126
+ disas_cc(s, insn); /* both imm and reg forms */
127
+ break;
128
+
129
+ case 0x4: /* Conditional select */
130
+ disas_cond_select(s, insn);
131
+ break;
132
+
133
+ case 0x6: /* Data-processing */
134
+ if (op0) { /* (1 source) */
135
+ disas_data_proc_1src(s, insn);
136
+ } else { /* (2 source) */
137
+ disas_data_proc_2src(s, insn);
138
+ }
139
+ break;
140
+ case 0x8 ... 0xf: /* (3 source) */
141
+ disas_data_proc_3src(s, insn);
142
+ break;
143
+
144
default:
145
+ do_unallocated:
146
unallocated_encoding(s);
147
break;
148
}
81
}
82
83
- /* Check that raw accesses are either forbidden or handled. Note that
84
+ /*
85
+ * Check that raw accesses are either forbidden or handled. Note that
86
* we can't assert this earlier because the setup of fieldoffset for
87
* banked registers has to be done first.
88
*/
149
--
89
--
150
2.20.1
90
2.25.1
151
152
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
In preparation for a split of the memory map into a static
3
Since e03b56863d2bc, our host endian indicator is unconditionally
4
part and a dynamic part floating after the RAM, let's rename the
4
set, which means that we can use a normal C condition.
5
regions located after the RAM
6
5
7
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
8
Message-id: 20220501055028.646596-20-richard.henderson@linaro.org
10
Message-id: 20190304101339.25970-3-eric.auger@redhat.com
9
[PMM: quote correct git hash in commit message]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
11
---
13
include/hw/arm/virt.h | 8 ++++----
12
target/arm/helper.c | 9 +++------
14
hw/arm/virt-acpi-build.c | 10 ++++++----
13
1 file changed, 3 insertions(+), 6 deletions(-)
15
hw/arm/virt.c | 33 ++++++++++++++++++---------------
16
3 files changed, 28 insertions(+), 23 deletions(-)
17
14
18
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/virt.h
17
--- a/target/arm/helper.c
21
+++ b/include/hw/arm/virt.h
18
+++ b/target/arm/helper.c
22
@@ -XXX,XX +XXX,XX @@ enum {
19
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
23
VIRT_GIC_VCPU,
20
r2->type |= ARM_CP_ALIAS;
24
VIRT_GIC_ITS,
25
VIRT_GIC_REDIST,
26
- VIRT_GIC_REDIST2,
27
+ VIRT_HIGH_GIC_REDIST2,
28
VIRT_SMMU,
29
VIRT_UART,
30
VIRT_MMIO,
31
@@ -XXX,XX +XXX,XX @@ enum {
32
VIRT_PCIE_MMIO,
33
VIRT_PCIE_PIO,
34
VIRT_PCIE_ECAM,
35
- VIRT_PCIE_ECAM_HIGH,
36
+ VIRT_HIGH_PCIE_ECAM,
37
VIRT_PLATFORM_BUS,
38
- VIRT_PCIE_MMIO_HIGH,
39
+ VIRT_HIGH_PCIE_MMIO,
40
VIRT_GPIO,
41
VIRT_SECURE_UART,
42
VIRT_SECURE_MEM,
43
@@ -XXX,XX +XXX,XX @@ typedef struct {
44
int psci_conduit;
45
} VirtMachineState;
46
47
-#define VIRT_ECAM_ID(high) (high ? VIRT_PCIE_ECAM_HIGH : VIRT_PCIE_ECAM)
48
+#define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)
49
50
#define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
51
#define VIRT_MACHINE(obj) \
52
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/hw/arm/virt-acpi-build.c
55
+++ b/hw/arm/virt-acpi-build.c
56
@@ -XXX,XX +XXX,XX @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
57
size_pio));
58
59
if (use_highmem) {
60
- hwaddr base_mmio_high = memmap[VIRT_PCIE_MMIO_HIGH].base;
61
- hwaddr size_mmio_high = memmap[VIRT_PCIE_MMIO_HIGH].size;
62
+ hwaddr base_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].base;
63
+ hwaddr size_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].size;
64
65
aml_append(rbuf,
66
aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
67
@@ -XXX,XX +XXX,XX @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
68
gicr = acpi_data_push(table_data, sizeof(*gicr));
69
gicr->type = ACPI_APIC_GENERIC_REDISTRIBUTOR;
70
gicr->length = sizeof(*gicr);
71
- gicr->base_address = cpu_to_le64(memmap[VIRT_GIC_REDIST2].base);
72
- gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST2].size);
73
+ gicr->base_address =
74
+ cpu_to_le64(memmap[VIRT_HIGH_GIC_REDIST2].base);
75
+ gicr->range_length =
76
+ cpu_to_le32(memmap[VIRT_HIGH_GIC_REDIST2].size);
77
}
21
}
78
22
79
if (its_class_name() && !vmc->no_its) {
23
- if (r->state == ARM_CP_STATE_BOTH) {
80
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
24
-#if HOST_BIG_ENDIAN
81
index XXXXXXX..XXXXXXX 100644
25
- if (r2->fieldoffset) {
82
--- a/hw/arm/virt.c
26
- r2->fieldoffset += sizeof(uint32_t);
83
+++ b/hw/arm/virt.c
27
- }
84
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry a15memmap[] = {
28
-#endif
85
[VIRT_PCIE_ECAM] = { 0x3f000000, 0x01000000 },
29
+ if (HOST_BIG_ENDIAN &&
86
[VIRT_MEM] = { 0x40000000, RAMLIMIT_BYTES },
30
+ r->state == ARM_CP_STATE_BOTH && r2->fieldoffset) {
87
/* Additional 64 MB redist region (can contain up to 512 redistributors) */
31
+ r2->fieldoffset += sizeof(uint32_t);
88
- [VIRT_GIC_REDIST2] = { 0x4000000000ULL, 0x4000000 },
89
- [VIRT_PCIE_ECAM_HIGH] = { 0x4010000000ULL, 0x10000000 },
90
+ [VIRT_HIGH_GIC_REDIST2] = { 0x4000000000ULL, 0x4000000 },
91
+ [VIRT_HIGH_PCIE_ECAM] = { 0x4010000000ULL, 0x10000000 },
92
/* Second PCIe window, 512GB wide at the 512GB boundary */
93
- [VIRT_PCIE_MMIO_HIGH] = { 0x8000000000ULL, 0x8000000000ULL },
94
+ [VIRT_HIGH_PCIE_MMIO] = { 0x8000000000ULL, 0x8000000000ULL },
95
};
96
97
static const int a15irqmap[] = {
98
@@ -XXX,XX +XXX,XX @@ static void fdt_add_gic_node(VirtMachineState *vms)
99
2, vms->memmap[VIRT_GIC_REDIST].size);
100
} else {
101
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
102
- 2, vms->memmap[VIRT_GIC_DIST].base,
103
- 2, vms->memmap[VIRT_GIC_DIST].size,
104
- 2, vms->memmap[VIRT_GIC_REDIST].base,
105
- 2, vms->memmap[VIRT_GIC_REDIST].size,
106
- 2, vms->memmap[VIRT_GIC_REDIST2].base,
107
- 2, vms->memmap[VIRT_GIC_REDIST2].size);
108
+ 2, vms->memmap[VIRT_GIC_DIST].base,
109
+ 2, vms->memmap[VIRT_GIC_DIST].size,
110
+ 2, vms->memmap[VIRT_GIC_REDIST].base,
111
+ 2, vms->memmap[VIRT_GIC_REDIST].size,
112
+ 2, vms->memmap[VIRT_HIGH_GIC_REDIST2].base,
113
+ 2, vms->memmap[VIRT_HIGH_GIC_REDIST2].size);
114
}
32
}
115
116
if (vms->virt) {
117
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
118
119
if (nb_redist_regions == 2) {
120
uint32_t redist1_capacity =
121
- vms->memmap[VIRT_GIC_REDIST2].size / GICV3_REDIST_SIZE;
122
+ vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
123
124
qdev_prop_set_uint32(gicdev, "redist-region-count[1]",
125
MIN(smp_cpus - redist0_count, redist1_capacity));
126
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
127
if (type == 3) {
128
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base);
129
if (nb_redist_regions == 2) {
130
- sysbus_mmio_map(gicbusdev, 2, vms->memmap[VIRT_GIC_REDIST2].base);
131
+ sysbus_mmio_map(gicbusdev, 2,
132
+ vms->memmap[VIRT_HIGH_GIC_REDIST2].base);
133
}
134
} else {
135
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_CPU].base);
136
@@ -XXX,XX +XXX,XX @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic)
137
{
138
hwaddr base_mmio = vms->memmap[VIRT_PCIE_MMIO].base;
139
hwaddr size_mmio = vms->memmap[VIRT_PCIE_MMIO].size;
140
- hwaddr base_mmio_high = vms->memmap[VIRT_PCIE_MMIO_HIGH].base;
141
- hwaddr size_mmio_high = vms->memmap[VIRT_PCIE_MMIO_HIGH].size;
142
+ hwaddr base_mmio_high = vms->memmap[VIRT_HIGH_PCIE_MMIO].base;
143
+ hwaddr size_mmio_high = vms->memmap[VIRT_HIGH_PCIE_MMIO].size;
144
hwaddr base_pio = vms->memmap[VIRT_PCIE_PIO].base;
145
hwaddr size_pio = vms->memmap[VIRT_PCIE_PIO].size;
146
hwaddr base_ecam, size_ecam;
147
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
148
* many redistributors we can fit into the memory map.
149
*/
150
if (vms->gic_version == 3) {
151
- virt_max_cpus = vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
152
- virt_max_cpus += vms->memmap[VIRT_GIC_REDIST2].size / GICV3_REDIST_SIZE;
153
+ virt_max_cpus =
154
+ vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
155
+ virt_max_cpus +=
156
+ vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
157
} else {
158
virt_max_cpus = GIC_NCPU;
159
}
33
}
34
160
--
35
--
161
2.20.1
36
2.25.1
162
163
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20190301200501.16533-11-richard.henderson@linaro.org
5
Message-id: 20220501055028.646596-24-richard.henderson@linaro.org
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
7
---
9
target/arm/cpu.h | 5 ++
8
target/arm/cpu.h | 15 +++++++++++++++
10
target/arm/helper.h | 5 ++
9
1 file changed, 15 insertions(+)
11
target/arm/cpu64.c | 1 +
12
target/arm/translate-a64.c | 71 ++++++++++++++++++++++++++--
13
target/arm/vfp_helper.c | 96 ++++++++++++++++++++++++++++++++++++++
14
5 files changed, 173 insertions(+), 5 deletions(-)
15
10
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
11
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
13
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
14
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_predinv(const ARMISARegisters *id)
15
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id)
21
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SPECRES) != 0;
16
return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0;
22
}
17
}
23
18
24
+static inline bool isar_feature_aa64_frint(const ARMISARegisters *id)
19
+static inline bool isar_feature_aa32_debugv8p2(const ARMISARegisters *id)
25
+{
20
+{
26
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0;
21
+ return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 8;
27
+}
22
+}
28
+
23
+
29
static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
24
/*
30
{
25
* 64-bit feature tests via id registers.
31
/* We always set the AdvSIMD and FP fields identically wrt FP16. */
26
*/
32
diff --git a/target/arm/helper.h b/target/arm/helper.h
27
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
33
index XXXXXXX..XXXXXXX 100644
28
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0;
34
--- a/target/arm/helper.h
35
+++ b/target/arm/helper.h
36
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fmlal_idx_a32, TCG_CALL_NO_RWG,
37
DEF_HELPER_FLAGS_5(gvec_fmlal_idx_a64, TCG_CALL_NO_RWG,
38
void, ptr, ptr, ptr, ptr, i32)
39
40
+DEF_HELPER_FLAGS_2(frint32_s, TCG_CALL_NO_RWG, f32, f32, ptr)
41
+DEF_HELPER_FLAGS_2(frint64_s, TCG_CALL_NO_RWG, f32, f32, ptr)
42
+DEF_HELPER_FLAGS_2(frint32_d, TCG_CALL_NO_RWG, f64, f64, ptr)
43
+DEF_HELPER_FLAGS_2(frint64_d, TCG_CALL_NO_RWG, f64, f64, ptr)
44
+
45
#ifdef TARGET_AARCH64
46
#include "helper-a64.h"
47
#include "helper-sve.h"
48
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/cpu64.c
51
+++ b/target/arm/cpu64.c
52
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
53
t = FIELD_DP64(t, ID_AA64ISAR1, GPI, 0);
54
t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1);
55
t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1);
56
+ t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1);
57
cpu->isar.id_aa64isar1 = t;
58
59
t = cpu->isar.id_aa64pfr0;
60
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/translate-a64.c
63
+++ b/target/arm/translate-a64.c
64
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
65
case 0xf: /* FRINTI */
66
gen_fpst = gen_helper_rints;
67
break;
68
+ case 0x10: /* FRINT32Z */
69
+ rmode = float_round_to_zero;
70
+ gen_fpst = gen_helper_frint32_s;
71
+ break;
72
+ case 0x11: /* FRINT32X */
73
+ gen_fpst = gen_helper_frint32_s;
74
+ break;
75
+ case 0x12: /* FRINT64Z */
76
+ rmode = float_round_to_zero;
77
+ gen_fpst = gen_helper_frint64_s;
78
+ break;
79
+ case 0x13: /* FRINT64X */
80
+ gen_fpst = gen_helper_frint64_s;
81
+ break;
82
default:
83
g_assert_not_reached();
84
}
85
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
86
case 0xf: /* FRINTI */
87
gen_fpst = gen_helper_rintd;
88
break;
89
+ case 0x10: /* FRINT32Z */
90
+ rmode = float_round_to_zero;
91
+ gen_fpst = gen_helper_frint32_d;
92
+ break;
93
+ case 0x11: /* FRINT32X */
94
+ gen_fpst = gen_helper_frint32_d;
95
+ break;
96
+ case 0x12: /* FRINT64Z */
97
+ rmode = float_round_to_zero;
98
+ gen_fpst = gen_helper_frint64_d;
99
+ break;
100
+ case 0x13: /* FRINT64X */
101
+ gen_fpst = gen_helper_frint64_d;
102
+ break;
103
default:
104
g_assert_not_reached();
105
}
106
@@ -XXX,XX +XXX,XX @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
107
handle_fp_fcvt(s, opcode, rd, rn, dtype, type);
108
break;
109
}
110
+
111
+ case 0x10 ... 0x13: /* FRINT{32,64}{X,Z} */
112
+ if (type > 1 || !dc_isar_feature(aa64_frint, s)) {
113
+ unallocated_encoding(s);
114
+ return;
115
+ }
116
+ /* fall through */
117
case 0x0 ... 0x3:
118
case 0x8 ... 0xc:
119
case 0xe ... 0xf:
120
@@ -XXX,XX +XXX,XX @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
121
if (!fp_access_check(s)) {
122
return;
123
}
124
-
125
handle_fp_1src_single(s, opcode, rd, rn);
126
break;
127
case 1:
128
if (!fp_access_check(s)) {
129
return;
130
}
131
-
132
handle_fp_1src_double(s, opcode, rd, rn);
133
break;
134
case 3:
135
@@ -XXX,XX +XXX,XX @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
136
if (!fp_access_check(s)) {
137
return;
138
}
139
-
140
handle_fp_1src_half(s, opcode, rd, rn);
141
break;
142
default:
143
unallocated_encoding(s);
144
}
145
break;
146
+
147
default:
148
unallocated_encoding(s);
149
break;
150
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_64(DisasContext *s, int opcode, bool u,
151
case 0x59: /* FRINTX */
152
gen_helper_rintd_exact(tcg_rd, tcg_rn, tcg_fpstatus);
153
break;
154
+ case 0x1e: /* FRINT32Z */
155
+ case 0x5e: /* FRINT32X */
156
+ gen_helper_frint32_d(tcg_rd, tcg_rn, tcg_fpstatus);
157
+ break;
158
+ case 0x1f: /* FRINT64Z */
159
+ case 0x5f: /* FRINT64X */
160
+ gen_helper_frint64_d(tcg_rd, tcg_rn, tcg_fpstatus);
161
+ break;
162
default:
163
g_assert_not_reached();
164
}
165
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
166
}
167
break;
168
case 0xc ... 0xf:
169
- case 0x16 ... 0x1d:
170
- case 0x1f:
171
+ case 0x16 ... 0x1f:
172
{
173
/* Floating point: U, size[1] and opcode indicate operation;
174
* size[0] indicates single or double precision.
175
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
176
}
177
need_fpstatus = true;
178
break;
179
+ case 0x1e: /* FRINT32Z */
180
+ case 0x1f: /* FRINT64Z */
181
+ need_rmode = true;
182
+ rmode = FPROUNDING_ZERO;
183
+ /* fall through */
184
+ case 0x5e: /* FRINT32X */
185
+ case 0x5f: /* FRINT64X */
186
+ need_fpstatus = true;
187
+ if ((size == 3 && !is_q) || !dc_isar_feature(aa64_frint, s)) {
188
+ unallocated_encoding(s);
189
+ return;
190
+ }
191
+ break;
192
default:
193
unallocated_encoding(s);
194
return;
195
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
196
case 0x7c: /* URSQRTE */
197
gen_helper_rsqrte_u32(tcg_res, tcg_op, tcg_fpstatus);
198
break;
199
+ case 0x1e: /* FRINT32Z */
200
+ case 0x5e: /* FRINT32X */
201
+ gen_helper_frint32_s(tcg_res, tcg_op, tcg_fpstatus);
202
+ break;
203
+ case 0x1f: /* FRINT64Z */
204
+ case 0x5f: /* FRINT64X */
205
+ gen_helper_frint64_s(tcg_res, tcg_op, tcg_fpstatus);
206
+ break;
207
default:
208
g_assert_not_reached();
209
}
210
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
211
index XXXXXXX..XXXXXXX 100644
212
--- a/target/arm/vfp_helper.c
213
+++ b/target/arm/vfp_helper.c
214
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vjcvt)(float64 value, CPUARMState *env)
215
216
return result;
217
}
29
}
218
+
30
219
+/* Round a float32 to an integer that fits in int32_t or int64_t. */
31
+static inline bool isar_feature_aa64_debugv8p2(const ARMISARegisters *id)
220
+static float32 frint_s(float32 f, float_status *fpst, int intsize)
221
+{
32
+{
222
+ int old_flags = get_float_exception_flags(fpst);
33
+ return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, DEBUGVER) >= 8;
223
+ uint32_t exp = extract32(f, 23, 8);
224
+
225
+ if (unlikely(exp == 0xff)) {
226
+ /* NaN or Inf. */
227
+ goto overflow;
228
+ }
229
+
230
+ /* Round and re-extract the exponent. */
231
+ f = float32_round_to_int(f, fpst);
232
+ exp = extract32(f, 23, 8);
233
+
234
+ /* Validate the range of the result. */
235
+ if (exp < 126 + intsize) {
236
+ /* abs(F) <= INT{N}_MAX */
237
+ return f;
238
+ }
239
+ if (exp == 126 + intsize) {
240
+ uint32_t sign = extract32(f, 31, 1);
241
+ uint32_t frac = extract32(f, 0, 23);
242
+ if (sign && frac == 0) {
243
+ /* F == INT{N}_MIN */
244
+ return f;
245
+ }
246
+ }
247
+
248
+ overflow:
249
+ /*
250
+ * Raise Invalid and return INT{N}_MIN as a float. Revert any
251
+ * inexact exception float32_round_to_int may have raised.
252
+ */
253
+ set_float_exception_flags(old_flags | float_flag_invalid, fpst);
254
+ return (0x100u + 126u + intsize) << 23;
255
+}
34
+}
256
+
35
+
257
+float32 HELPER(frint32_s)(float32 f, void *fpst)
36
static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id)
37
{
38
return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SVEVER) != 0;
39
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id)
40
return isar_feature_aa64_tts2uxn(id) || isar_feature_aa32_tts2uxn(id);
41
}
42
43
+static inline bool isar_feature_any_debugv8p2(const ARMISARegisters *id)
258
+{
44
+{
259
+ return frint_s(f, fpst, 32);
45
+ return isar_feature_aa64_debugv8p2(id) || isar_feature_aa32_debugv8p2(id);
260
+}
46
+}
261
+
47
+
262
+float32 HELPER(frint64_s)(float32 f, void *fpst)
48
/*
263
+{
49
* Forward to the above feature tests given an ARMCPU pointer.
264
+ return frint_s(f, fpst, 64);
50
*/
265
+}
266
+
267
+/* Round a float64 to an integer that fits in int32_t or int64_t. */
268
+static float64 frint_d(float64 f, float_status *fpst, int intsize)
269
+{
270
+ int old_flags = get_float_exception_flags(fpst);
271
+ uint32_t exp = extract64(f, 52, 11);
272
+
273
+ if (unlikely(exp == 0x7ff)) {
274
+ /* NaN or Inf. */
275
+ goto overflow;
276
+ }
277
+
278
+ /* Round and re-extract the exponent. */
279
+ f = float64_round_to_int(f, fpst);
280
+ exp = extract64(f, 52, 11);
281
+
282
+ /* Validate the range of the result. */
283
+ if (exp < 1022 + intsize) {
284
+ /* abs(F) <= INT{N}_MAX */
285
+ return f;
286
+ }
287
+ if (exp == 1022 + intsize) {
288
+ uint64_t sign = extract64(f, 63, 1);
289
+ uint64_t frac = extract64(f, 0, 52);
290
+ if (sign && frac == 0) {
291
+ /* F == INT{N}_MIN */
292
+ return f;
293
+ }
294
+ }
295
+
296
+ overflow:
297
+ /*
298
+ * Raise Invalid and return INT{N}_MIN as a float. Revert any
299
+ * inexact exception float64_round_to_int may have raised.
300
+ */
301
+ set_float_exception_flags(old_flags | float_flag_invalid, fpst);
302
+ return (uint64_t)(0x800 + 1022 + intsize) << 52;
303
+}
304
+
305
+float64 HELPER(frint32_d)(float64 f, void *fpst)
306
+{
307
+ return frint_d(f, fpst, 32);
308
+}
309
+
310
+float64 HELPER(frint64_d)(float64 f, void *fpst)
311
+{
312
+ return frint_d(f, fpst, 64);
313
+}
314
--
51
--
315
2.20.1
52
2.25.1
316
317
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
3
Add the aa64 predicate for detecting RAS support from id registers.
4
We already have the aa32 version from the M-profile work.
5
Add the 'any' predicate for testing both aa64 and aa32.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20190301200501.16533-8-richard.henderson@linaro.org
9
Message-id: 20220501055028.646596-34-richard.henderson@linaro.org
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
[PMM: fixed up block comment style]
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
target/arm/cpu.h | 5 ++
12
target/arm/cpu.h | 10 ++++++++++
11
linux-user/elfload.c | 1 +
13
1 file changed, 10 insertions(+)
12
target/arm/cpu64.c | 1 +
13
target/arm/translate-a64.c | 99 +++++++++++++++++++++++++++++++++++++-
14
4 files changed, 105 insertions(+), 1 deletion(-)
15
14
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
17
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_fhm(const ARMISARegisters *id)
19
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id)
21
return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, FHM) != 0;
20
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2;
22
}
21
}
23
22
24
+static inline bool isar_feature_aa64_condm_4(const ARMISARegisters *id)
23
+static inline bool isar_feature_aa64_ras(const ARMISARegisters *id)
25
+{
24
+{
26
+ return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) != 0;
25
+ return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) != 0;
27
+}
26
+}
28
+
27
+
29
static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id)
28
static inline bool isar_feature_aa64_sve(const ARMISARegisters *id)
30
{
29
{
31
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0;
30
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0;
32
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
31
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_any_debugv8p2(const ARMISARegisters *id)
33
index XXXXXXX..XXXXXXX 100644
32
return isar_feature_aa64_debugv8p2(id) || isar_feature_aa32_debugv8p2(id);
34
--- a/linux-user/elfload.c
35
+++ b/linux-user/elfload.c
36
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
37
GET_FEATURE_ID(aa64_fhm, ARM_HWCAP_A64_ASIMDFHM);
38
GET_FEATURE_ID(aa64_jscvt, ARM_HWCAP_A64_JSCVT);
39
GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB);
40
+ GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM);
41
42
#undef GET_FEATURE_ID
43
44
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/cpu64.c
47
+++ b/target/arm/cpu64.c
48
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
49
t = FIELD_DP64(t, ID_AA64ISAR0, SM4, 1);
50
t = FIELD_DP64(t, ID_AA64ISAR0, DP, 1);
51
t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 1);
52
+ t = FIELD_DP64(t, ID_AA64ISAR0, TS, 1);
53
cpu->isar.id_aa64isar0 = t;
54
55
t = cpu->isar.id_aa64isar1;
56
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/translate-a64.c
59
+++ b/target/arm/translate-a64.c
60
@@ -XXX,XX +XXX,XX @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
61
s->base.is_jmp = DISAS_TOO_MANY;
62
63
switch (op) {
64
+ case 0x00: /* CFINV */
65
+ if (crm != 0 || !dc_isar_feature(aa64_condm_4, s)) {
66
+ goto do_unallocated;
67
+ }
68
+ tcg_gen_xori_i32(cpu_CF, cpu_CF, 1);
69
+ s->base.is_jmp = DISAS_NEXT;
70
+ break;
71
+
72
case 0x05: /* SPSel */
73
if (s->current_el == 0) {
74
goto do_unallocated;
75
@@ -XXX,XX +XXX,XX @@ static void gen_get_nzcv(TCGv_i64 tcg_rt)
76
}
33
}
77
34
78
static void gen_set_nzcv(TCGv_i64 tcg_rt)
35
+static inline bool isar_feature_any_ras(const ARMISARegisters *id)
79
-
80
{
81
TCGv_i32 nzcv = tcg_temp_new_i32();
82
83
@@ -XXX,XX +XXX,XX @@ static void disas_adc_sbc(DisasContext *s, uint32_t insn)
84
}
85
}
86
87
+/*
88
+ * Rotate right into flags
89
+ * 31 30 29 21 15 10 5 4 0
90
+ * +--+--+--+-----------------+--------+-----------+------+--+------+
91
+ * |sf|op| S| 1 1 0 1 0 0 0 0 | imm6 | 0 0 0 0 1 | Rn |o2| mask |
92
+ * +--+--+--+-----------------+--------+-----------+------+--+------+
93
+ */
94
+static void disas_rotate_right_into_flags(DisasContext *s, uint32_t insn)
95
+{
36
+{
96
+ int mask = extract32(insn, 0, 4);
37
+ return isar_feature_aa64_ras(id) || isar_feature_aa32_ras(id);
97
+ int o2 = extract32(insn, 4, 1);
98
+ int rn = extract32(insn, 5, 5);
99
+ int imm6 = extract32(insn, 15, 6);
100
+ int sf_op_s = extract32(insn, 29, 3);
101
+ TCGv_i64 tcg_rn;
102
+ TCGv_i32 nzcv;
103
+
104
+ if (sf_op_s != 5 || o2 != 0 || !dc_isar_feature(aa64_condm_4, s)) {
105
+ unallocated_encoding(s);
106
+ return;
107
+ }
108
+
109
+ tcg_rn = read_cpu_reg(s, rn, 1);
110
+ tcg_gen_rotri_i64(tcg_rn, tcg_rn, imm6);
111
+
112
+ nzcv = tcg_temp_new_i32();
113
+ tcg_gen_extrl_i64_i32(nzcv, tcg_rn);
114
+
115
+ if (mask & 8) { /* N */
116
+ tcg_gen_shli_i32(cpu_NF, nzcv, 31 - 3);
117
+ }
118
+ if (mask & 4) { /* Z */
119
+ tcg_gen_not_i32(cpu_ZF, nzcv);
120
+ tcg_gen_andi_i32(cpu_ZF, cpu_ZF, 4);
121
+ }
122
+ if (mask & 2) { /* C */
123
+ tcg_gen_extract_i32(cpu_CF, nzcv, 1, 1);
124
+ }
125
+ if (mask & 1) { /* V */
126
+ tcg_gen_shli_i32(cpu_VF, nzcv, 31 - 0);
127
+ }
128
+
129
+ tcg_temp_free_i32(nzcv);
130
+}
38
+}
131
+
39
+
132
+/*
40
/*
133
+ * Evaluate into flags
41
* Forward to the above feature tests given an ARMCPU pointer.
134
+ * 31 30 29 21 15 14 10 5 4 0
42
*/
135
+ * +--+--+--+-----------------+---------+----+---------+------+--+------+
136
+ * |sf|op| S| 1 1 0 1 0 0 0 0 | opcode2 | sz | 0 0 1 0 | Rn |o3| mask |
137
+ * +--+--+--+-----------------+---------+----+---------+------+--+------+
138
+ */
139
+static void disas_evaluate_into_flags(DisasContext *s, uint32_t insn)
140
+{
141
+ int o3_mask = extract32(insn, 0, 5);
142
+ int rn = extract32(insn, 5, 5);
143
+ int o2 = extract32(insn, 15, 6);
144
+ int sz = extract32(insn, 14, 1);
145
+ int sf_op_s = extract32(insn, 29, 3);
146
+ TCGv_i32 tmp;
147
+ int shift;
148
+
149
+ if (sf_op_s != 1 || o2 != 0 || o3_mask != 0xd ||
150
+ !dc_isar_feature(aa64_condm_4, s)) {
151
+ unallocated_encoding(s);
152
+ return;
153
+ }
154
+ shift = sz ? 16 : 24; /* SETF16 or SETF8 */
155
+
156
+ tmp = tcg_temp_new_i32();
157
+ tcg_gen_extrl_i64_i32(tmp, cpu_reg(s, rn));
158
+ tcg_gen_shli_i32(cpu_NF, tmp, shift);
159
+ tcg_gen_shli_i32(cpu_VF, tmp, shift - 1);
160
+ tcg_gen_mov_i32(cpu_ZF, cpu_NF);
161
+ tcg_gen_xor_i32(cpu_VF, cpu_VF, cpu_NF);
162
+ tcg_temp_free_i32(tmp);
163
+}
164
+
165
/* Conditional compare (immediate / register)
166
* 31 30 29 28 27 26 25 24 23 22 21 20 16 15 12 11 10 9 5 4 3 0
167
* +--+--+--+------------------------+--------+------+----+--+------+--+-----+
168
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
169
disas_adc_sbc(s, insn);
170
break;
171
172
+ case 0x01: /* Rotate right into flags */
173
+ case 0x21:
174
+ disas_rotate_right_into_flags(s, insn);
175
+ break;
176
+
177
+ case 0x02: /* Evaluate into flags */
178
+ case 0x12:
179
+ case 0x22:
180
+ case 0x32:
181
+ disas_evaluate_into_flags(s, insn);
182
+ break;
183
+
184
default:
185
goto do_unallocated;
186
}
187
--
43
--
188
2.20.1
44
2.25.1
189
190
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Alex Zuepke <alex.zuepke@tum.de>
2
2
3
On ARM, the kvm_type will be resolved by querying the KVMState.
3
The ARMv8 manual defines that PMUSERENR_EL0.ER enables read-access
4
Let's add the MachineState handle to the callback so that we
4
to both PMXEVCNTR_EL0 and PMEVCNTR<n>_EL0 registers, however,
5
can retrieve the KVMState handle. in kvm_init, when the callback
5
we only use it for PMXEVCNTR_EL0. Extend to PMEVCNTR<n>_EL0 as well.
6
is called, the kvm_state variable is not yet set.
7
6
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
7
Signed-off-by: Alex Zuepke <alex.zuepke@tum.de>
9
Acked-by: David Gibson <david@gibson.dropbear.id.au>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20220428132717.84190-1-alex.zuepke@tum.de
11
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
12
Message-id: 20190304101339.25970-5-eric.auger@redhat.com
13
[ppc parts]
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
11
---
18
include/hw/boards.h | 5 ++++-
12
target/arm/helper.c | 4 ++--
19
accel/kvm/kvm-all.c | 2 +-
13
1 file changed, 2 insertions(+), 2 deletions(-)
20
hw/ppc/mac_newworld.c | 3 +--
21
hw/ppc/mac_oldworld.c | 2 +-
22
hw/ppc/spapr.c | 2 +-
23
5 files changed, 8 insertions(+), 6 deletions(-)
24
14
25
diff --git a/include/hw/boards.h b/include/hw/boards.h
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
26
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
27
--- a/include/hw/boards.h
17
--- a/target/arm/helper.c
28
+++ b/include/hw/boards.h
18
+++ b/target/arm/helper.c
29
@@ -XXX,XX +XXX,XX @@ typedef struct {
19
@@ -XXX,XX +XXX,XX @@ static void define_pmu_regs(ARMCPU *cpu)
30
* should instead use "unimplemented-device" for all memory ranges where
20
.crm = 8 | (3 & (i >> 3)), .opc1 = 0, .opc2 = i & 7,
31
* the guest will attempt to probe for a device that QEMU doesn't
21
.access = PL0_RW, .type = ARM_CP_IO | ARM_CP_ALIAS,
32
* implement and a stub device is required.
22
.readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
33
+ * @kvm_type:
23
- .accessfn = pmreg_access },
34
+ * Return the type of KVM corresponding to the kvm-type string option or
24
+ .accessfn = pmreg_access_xevcntr },
35
+ * computed based on other criteria such as the host kernel capabilities.
25
{ .name = pmevcntr_el0_name, .state = ARM_CP_STATE_AA64,
36
*/
26
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 8 | (3 & (i >> 3)),
37
struct MachineClass {
27
- .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access,
38
/*< private >*/
28
+ .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access_xevcntr,
39
@@ -XXX,XX +XXX,XX @@ struct MachineClass {
29
.type = ARM_CP_IO,
40
void (*init)(MachineState *state);
30
.readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
41
void (*reset)(void);
31
.raw_readfn = pmevcntr_rawread,
42
void (*hot_add_cpu)(const int64_t id, Error **errp);
43
- int (*kvm_type)(const char *arg);
44
+ int (*kvm_type)(MachineState *machine, const char *arg);
45
46
BlockInterfaceType block_default_type;
47
int units_per_default_bus;
48
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/accel/kvm/kvm-all.c
51
+++ b/accel/kvm/kvm-all.c
52
@@ -XXX,XX +XXX,XX @@ static int kvm_init(MachineState *ms)
53
54
kvm_type = qemu_opt_get(qemu_get_machine_opts(), "kvm-type");
55
if (mc->kvm_type) {
56
- type = mc->kvm_type(kvm_type);
57
+ type = mc->kvm_type(ms, kvm_type);
58
} else if (kvm_type) {
59
ret = -EINVAL;
60
fprintf(stderr, "Invalid argument kvm-type=%s\n", kvm_type);
61
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/ppc/mac_newworld.c
64
+++ b/hw/ppc/mac_newworld.c
65
@@ -XXX,XX +XXX,XX @@ static char *core99_fw_dev_path(FWPathProvider *p, BusState *bus,
66
67
return NULL;
68
}
69
-
70
-static int core99_kvm_type(const char *arg)
71
+static int core99_kvm_type(MachineState *machine, const char *arg)
72
{
73
/* Always force PR KVM */
74
return 2;
75
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/hw/ppc/mac_oldworld.c
78
+++ b/hw/ppc/mac_oldworld.c
79
@@ -XXX,XX +XXX,XX @@ static char *heathrow_fw_dev_path(FWPathProvider *p, BusState *bus,
80
return NULL;
81
}
82
83
-static int heathrow_kvm_type(const char *arg)
84
+static int heathrow_kvm_type(MachineState *machine, const char *arg)
85
{
86
/* Always force PR KVM */
87
return 2;
88
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/hw/ppc/spapr.c
91
+++ b/hw/ppc/spapr.c
92
@@ -XXX,XX +XXX,XX @@ static void spapr_machine_init(MachineState *machine)
93
}
94
}
95
96
-static int spapr_kvm_type(const char *vm_type)
97
+static int spapr_kvm_type(MachineState *machine, const char *vm_type)
98
{
99
if (!vm_type) {
100
return 0;
101
--
32
--
102
2.20.1
33
2.25.1
103
104
diff view generated by jsdifflib