1
Couple of minor patches to sneak in before rc0. The PSCI return
1
The following changes since commit 3214bec13d8d4c40f707d21d8350d04e4123ae97:
2
values fix is the most important one.
3
2
4
-- PMM
3
Merge tag 'migration-20250110-pull-request' of https://gitlab.com/farosas/qemu into staging (2025-01-10 13:39:19 -0500)
5
4
6
The following changes since commit 94b5d57d2f5a3c849cecd65e424bb6f50b998df9:
5
are available in the Git repository at:
7
6
8
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.9-20170314' into staging (2017-03-14 10:13:19 +0000)
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20250113
9
8
10
are available in the git repository at:
9
for you to fetch changes up to 435d260e7ec5ff9c79e3e62f1d66ec82d2d691ae:
11
10
12
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20170314
11
docs/system/arm/virt: mention specific migration information (2025-01-13 12:35:35 +0000)
13
14
for you to fetch changes up to d5affb0d8677e1a8a8fe03fa25005b669e7cdc02:
15
16
target/arm/arm-powerctl: Fix psci info return values (2017-03-14 11:28:54 +0000)
17
12
18
----------------------------------------------------------------
13
----------------------------------------------------------------
19
target-arm queue:
14
target-arm queue:
20
* arm-powerctl: Fix psci info return values
15
* hw/arm_sysctl: fix extracting 31th bit of val
21
* implement armv8 PMUSERENR (user-mode enable bits)
16
* hw/misc: cast rpm to uint64_t
17
* tests/qtest/boot-serial-test: Improve ASM
18
* target/arm: Move minor arithmetic helpers out of helper.c
19
* target/arm: change default pauth algorithm to impdef
22
20
23
----------------------------------------------------------------
21
----------------------------------------------------------------
24
Andrew Baumann (1):
22
Anastasia Belova (1):
25
target/arm: implement armv8 PMUSERENR (user-mode enable bits)
23
hw/arm_sysctl: fix extracting 31th bit of val
26
24
27
Andrew Jones (1):
25
Peter Maydell (2):
28
target/arm/arm-powerctl: Fix psci info return values
26
target/arm: Move minor arithmetic helpers out of helper.c
27
tests/tcg/aarch64: force qarma5 for pauth-3 test
29
28
30
target/arm/cpu.h | 4 +--
29
Philippe Mathieu-Daudé (4):
31
target/arm/helper.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++------
30
tests/qtest/boot-serial-test: Improve ASM comments of PL011 tests
32
2 files changed, 73 insertions(+), 10 deletions(-)
31
tests/qtest/boot-serial-test: Reduce for() loop in PL011 tests
32
tests/qtest/boot-serial-test: Reorder pair of instructions in PL011 test
33
tests/qtest/boot-serial-test: Initialize PL011 Control register
33
34
35
Pierrick Bouvier (3):
36
target/arm: add new property to select pauth-qarma5
37
target/arm: change default pauth algorithm to impdef
38
docs/system/arm/virt: mention specific migration information
39
40
Tigran Sogomonian (1):
41
hw/misc: cast rpm to uint64_t
42
43
docs/system/arm/cpu-features.rst | 7 +-
44
docs/system/arm/virt.rst | 4 +
45
docs/system/introduction.rst | 2 +-
46
target/arm/cpu.h | 4 +
47
hw/core/machine.c | 4 +-
48
hw/misc/arm_sysctl.c | 2 +-
49
hw/misc/npcm7xx_mft.c | 5 +-
50
target/arm/arm-qmp-cmds.c | 2 +-
51
target/arm/cpu.c | 2 +
52
target/arm/cpu64.c | 38 ++-
53
target/arm/helper.c | 285 -----------------------
54
target/arm/tcg/arith_helper.c | 296 ++++++++++++++++++++++++
55
tests/qtest/arm-cpu-features.c | 15 +-
56
tests/qtest/boot-serial-test.c | 23 +-
57
target/arm/{op_addsub.h => tcg/op_addsub.c.inc} | 0
58
target/arm/tcg/meson.build | 1 +
59
tests/tcg/aarch64/Makefile.softmmu-target | 3 +
60
17 files changed, 377 insertions(+), 316 deletions(-)
61
create mode 100644 target/arm/tcg/arith_helper.c
62
rename target/arm/{op_addsub.h => tcg/op_addsub.c.inc} (100%)
63
diff view generated by jsdifflib
New patch
1
From: Anastasia Belova <abelova@astralinux.ru>
1
2
3
1 << 31 is casted to uint64_t while bitwise and with val.
4
So this value may become 0xffffffff80000000 but only
5
31th "start" bit is required.
6
7
This is not possible in practice because the MemoryRegionOps
8
uses the default max access size of 4 bytes and so none
9
of the upper bytes of val will be set, but the bitfield
10
extract API is clearer anyway.
11
12
Use the bitfield extract() API instead.
13
14
Found by Linux Verification Center (linuxtesting.org) with SVACE.
15
16
Signed-off-by: Anastasia Belova <abelova@astralinux.ru>
17
Message-id: 20241220125429.7552-1-abelova@astralinux.ru
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
[PMM: add clarification to commit message]
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
22
hw/misc/arm_sysctl.c | 2 +-
23
1 file changed, 1 insertion(+), 1 deletion(-)
24
25
diff --git a/hw/misc/arm_sysctl.c b/hw/misc/arm_sysctl.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/misc/arm_sysctl.c
28
+++ b/hw/misc/arm_sysctl.c
29
@@ -XXX,XX +XXX,XX @@ static void arm_sysctl_write(void *opaque, hwaddr offset,
30
* as zero.
31
*/
32
s->sys_cfgctrl = val & ~((3 << 18) | (1 << 31));
33
- if (val & (1 << 31)) {
34
+ if (extract64(val, 31, 1)) {
35
/* Start bit set -- actually do something */
36
unsigned int dcc = extract32(s->sys_cfgctrl, 26, 4);
37
unsigned int function = extract32(s->sys_cfgctrl, 20, 6);
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
From: Tigran Sogomonian <tsogomonian@astralinux.ru>
1
2
3
The value of an arithmetic expression
4
'rpm * NPCM7XX_MFT_PULSE_PER_REVOLUTION' is a subject
5
to overflow because its operands are not cast to
6
a larger data type before performing arithmetic. Thus, need
7
to cast rpm to uint64_t.
8
9
Found by Linux Verification Center (linuxtesting.org) with SVACE.
10
11
Signed-off-by: Tigran Sogomonian <tsogomonian@astralinux.ru>
12
Reviewed-by: Patrick Leis <venture@google.com>
13
Reviewed-by: Hao Wu <wuhaotsh@google.com>
14
Message-id: 20241226130311.1349-1-tsogomonian@astralinux.ru
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
hw/misc/npcm7xx_mft.c | 5 +++--
18
1 file changed, 3 insertions(+), 2 deletions(-)
19
20
diff --git a/hw/misc/npcm7xx_mft.c b/hw/misc/npcm7xx_mft.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/npcm7xx_mft.c
23
+++ b/hw/misc/npcm7xx_mft.c
24
@@ -XXX,XX +XXX,XX @@ static NPCM7xxMFTCaptureState npcm7xx_mft_compute_cnt(
25
* RPM = revolution/min. The time for one revlution (in ns) is
26
* MINUTE_TO_NANOSECOND / RPM.
27
*/
28
- count = clock_ns_to_ticks(clock, (60 * NANOSECONDS_PER_SECOND) /
29
- (rpm * NPCM7XX_MFT_PULSE_PER_REVOLUTION));
30
+ count = clock_ns_to_ticks(clock,
31
+ (uint64_t)(60 * NANOSECONDS_PER_SECOND) /
32
+ ((uint64_t)rpm * NPCM7XX_MFT_PULSE_PER_REVOLUTION));
33
}
34
35
if (count > NPCM7XX_MFT_MAX_CNT) {
36
--
37
2.34.1
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
2
3
Re-indent ASM comments adding the 'loop:' label.
4
5
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Fabiano Rosas <farosas@suse.de>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
tests/qtest/boot-serial-test.c | 18 +++++++++---------
11
1 file changed, 9 insertions(+), 9 deletions(-)
12
13
diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/qtest/boot-serial-test.c
16
+++ b/tests/qtest/boot-serial-test.c
17
@@ -XXX,XX +XXX,XX @@ static const uint8_t kernel_plml605[] = {
18
};
19
20
static const uint8_t bios_raspi2[] = {
21
- 0x08, 0x30, 0x9f, 0xe5, /* ldr r3,[pc,#8] Get base */
22
- 0x54, 0x20, 0xa0, 0xe3, /* mov r2,#'T' */
23
- 0x00, 0x20, 0xc3, 0xe5, /* strb r2,[r3] */
24
- 0xfb, 0xff, 0xff, 0xea, /* b loop */
25
- 0x00, 0x10, 0x20, 0x3f, /* 0x3f201000 = UART0 base addr */
26
+ 0x08, 0x30, 0x9f, 0xe5, /* loop: ldr r3, [pc, #8] Get &UART0 */
27
+ 0x54, 0x20, 0xa0, 0xe3, /* mov r2, #'T' */
28
+ 0x00, 0x20, 0xc3, 0xe5, /* strb r2, [r3] *TXDAT = 'T' */
29
+ 0xfb, 0xff, 0xff, 0xea, /* b -12 (loop) */
30
+ 0x00, 0x10, 0x20, 0x3f, /* UART0: 0x3f201000 */
31
};
32
33
static const uint8_t kernel_aarch64[] = {
34
- 0x81, 0x0a, 0x80, 0x52, /* mov w1, #0x54 */
35
- 0x02, 0x20, 0xa1, 0xd2, /* mov x2, #0x9000000 */
36
- 0x41, 0x00, 0x00, 0x39, /* strb w1, [x2] */
37
- 0xfd, 0xff, 0xff, 0x17, /* b -12 (loop) */
38
+ 0x81, 0x0a, 0x80, 0x52, /* loop: mov w1, #'T' */
39
+ 0x02, 0x20, 0xa1, 0xd2, /* mov x2, #0x9000000 Load UART0 */
40
+ 0x41, 0x00, 0x00, 0x39, /* strb w1, [x2] *TXDAT = 'T' */
41
+ 0xfd, 0xff, 0xff, 0x17, /* b -12 (loop) */
42
};
43
44
static const uint8_t kernel_nrf51[] = {
45
--
46
2.34.1
47
48
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
2
3
Since registers are not modified, we don't need
4
to refill their values. Directly jump to the previous
5
store instruction to keep filling the TXDAT register.
6
7
The equivalent C code remains:
8
9
while (true) {
10
*UART_DATA = 'T';
11
}
12
13
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Fabiano Rosas <farosas@suse.de>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
tests/qtest/boot-serial-test.c | 12 ++++++------
19
1 file changed, 6 insertions(+), 6 deletions(-)
20
21
diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/tests/qtest/boot-serial-test.c
24
+++ b/tests/qtest/boot-serial-test.c
25
@@ -XXX,XX +XXX,XX @@ static const uint8_t kernel_plml605[] = {
26
};
27
28
static const uint8_t bios_raspi2[] = {
29
- 0x08, 0x30, 0x9f, 0xe5, /* loop: ldr r3, [pc, #8] Get &UART0 */
30
+ 0x08, 0x30, 0x9f, 0xe5, /* ldr r3, [pc, #8] Get &UART0 */
31
0x54, 0x20, 0xa0, 0xe3, /* mov r2, #'T' */
32
- 0x00, 0x20, 0xc3, 0xe5, /* strb r2, [r3] *TXDAT = 'T' */
33
- 0xfb, 0xff, 0xff, 0xea, /* b -12 (loop) */
34
+ 0x00, 0x20, 0xc3, 0xe5, /* loop: strb r2, [r3] *TXDAT = 'T' */
35
+ 0xff, 0xff, 0xff, 0xea, /* b -4 (loop) */
36
0x00, 0x10, 0x20, 0x3f, /* UART0: 0x3f201000 */
37
};
38
39
static const uint8_t kernel_aarch64[] = {
40
- 0x81, 0x0a, 0x80, 0x52, /* loop: mov w1, #'T' */
41
+ 0x81, 0x0a, 0x80, 0x52, /* mov w1, #'T' */
42
0x02, 0x20, 0xa1, 0xd2, /* mov x2, #0x9000000 Load UART0 */
43
- 0x41, 0x00, 0x00, 0x39, /* strb w1, [x2] *TXDAT = 'T' */
44
- 0xfd, 0xff, 0xff, 0x17, /* b -12 (loop) */
45
+ 0x41, 0x00, 0x00, 0x39, /* loop: strb w1, [x2] *TXDAT = 'T' */
46
+ 0xff, 0xff, 0xff, 0x17, /* b -4 (loop) */
47
};
48
49
static const uint8_t kernel_nrf51[] = {
50
--
51
2.34.1
52
53
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
2
3
In the next commit we are going to use a different value
4
for the $w1 register, maintaining the same $x2 value. In
5
order to keep the next commit trivial to review, set $x2
6
before $w1.
7
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Fabiano Rosas <farosas@suse.de>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
tests/qtest/boot-serial-test.c | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qtest/boot-serial-test.c
19
+++ b/tests/qtest/boot-serial-test.c
20
@@ -XXX,XX +XXX,XX @@ static const uint8_t bios_raspi2[] = {
21
};
22
23
static const uint8_t kernel_aarch64[] = {
24
- 0x81, 0x0a, 0x80, 0x52, /* mov w1, #'T' */
25
0x02, 0x20, 0xa1, 0xd2, /* mov x2, #0x9000000 Load UART0 */
26
+ 0x81, 0x0a, 0x80, 0x52, /* mov w1, #'T' */
27
0x41, 0x00, 0x00, 0x39, /* loop: strb w1, [x2] *TXDAT = 'T' */
28
0xff, 0xff, 0xff, 0x17, /* b -4 (loop) */
29
};
30
--
31
2.34.1
32
33
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
2
3
The tests using the PL011 UART of the virt and raspi machines
4
weren't properly enabling the UART and its transmitter previous
5
to sending characters. Follow the PL011 manual initialization
6
recommendation by setting the proper bits of the control register.
7
8
Update the ASM code prefixing:
9
10
*UART_CTRL = UART_ENABLE | TX_ENABLE;
11
12
to:
13
14
while (true) {
15
*UART_DATA = 'T';
16
}
17
18
Note, since commit 51b61dd4d56 ("hw/char/pl011: Warn when using
19
disabled transmitter") incomplete PL011 initialization can be
20
logged using the '-d guest_errors' command line option.
21
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
---
26
tests/qtest/boot-serial-test.c | 7 ++++++-
27
1 file changed, 6 insertions(+), 1 deletion(-)
28
29
diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/tests/qtest/boot-serial-test.c
32
+++ b/tests/qtest/boot-serial-test.c
33
@@ -XXX,XX +XXX,XX @@ static const uint8_t kernel_plml605[] = {
34
};
35
36
static const uint8_t bios_raspi2[] = {
37
- 0x08, 0x30, 0x9f, 0xe5, /* ldr r3, [pc, #8] Get &UART0 */
38
+ 0x10, 0x30, 0x9f, 0xe5, /* ldr r3, [pc, #16] Get &UART0 */
39
+ 0x10, 0x20, 0x9f, 0xe5, /* ldr r2, [pc, #16] Get &CR */
40
+ 0xb0, 0x23, 0xc3, 0xe1, /* strh r2, [r3, #48] Set CR */
41
0x54, 0x20, 0xa0, 0xe3, /* mov r2, #'T' */
42
0x00, 0x20, 0xc3, 0xe5, /* loop: strb r2, [r3] *TXDAT = 'T' */
43
0xff, 0xff, 0xff, 0xea, /* b -4 (loop) */
44
0x00, 0x10, 0x20, 0x3f, /* UART0: 0x3f201000 */
45
+ 0x01, 0x01, 0x00, 0x00, /* CR: 0x101 = UARTEN|TXE */
46
};
47
48
static const uint8_t kernel_aarch64[] = {
49
0x02, 0x20, 0xa1, 0xd2, /* mov x2, #0x9000000 Load UART0 */
50
+ 0x21, 0x20, 0x80, 0x52, /* mov w1, 0x101 CR = UARTEN|TXE */
51
+ 0x41, 0x60, 0x00, 0x79, /* strh w1, [x2, #48] Set CR */
52
0x81, 0x0a, 0x80, 0x52, /* mov w1, #'T' */
53
0x41, 0x00, 0x00, 0x39, /* loop: strb w1, [x2] *TXDAT = 'T' */
54
0xff, 0xff, 0xff, 0x17, /* b -4 (loop) */
55
--
56
2.34.1
57
58
diff view generated by jsdifflib
1
From: Andrew Baumann <Andrew.Baumann@microsoft.com>
1
helper.c includes some small TCG helper functions used for mostly
2
arithmetic instructions. These are TCG only and there's no need for
3
them to be in the large and unwieldy helper.c. Move them out to
4
their own source file in the tcg/ subdirectory, together with the
5
op_addsub.h multiply-included template header that they use.
2
6
3
In armv8, this register implements more than a single bit, with
7
Since we are moving op_addsub.h, we take the opportunity to
4
fine-grained enables for read access to event counters, cycles
8
give it a name which matches our convention for files which
5
counters, and write access to the software increment. This change
9
are not true header files but which are #included from other
6
implements those checks using custom access functions for the relevant
10
C files: op_addsub.c.inc.
7
registers.
8
11
9
Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
12
(Ironically, this means that helper.c no longer contains
10
Message-id: 20170228215801.10472-2-Andrew.Baumann@microsoft.com
13
any TCG helper function definitions at all.)
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
12
[PMM: move a couple of access functions to be only compiled
13
ifndef CONFIG_USER_ONLY to avoid compiler warnings]
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20250110131211.2546314-1-peter.maydell@linaro.org
18
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
15
---
19
---
16
target/arm/helper.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++------
20
target/arm/helper.c | 285 -----------------
17
1 file changed, 71 insertions(+), 8 deletions(-)
21
target/arm/tcg/arith_helper.c | 296 ++++++++++++++++++
22
.../arm/{op_addsub.h => tcg/op_addsub.c.inc} | 0
23
target/arm/tcg/meson.build | 1 +
24
4 files changed, 297 insertions(+), 285 deletions(-)
25
create mode 100644 target/arm/tcg/arith_helper.c
26
rename target/arm/{op_addsub.h => tcg/op_addsub.c.inc} (100%)
18
27
19
diff --git a/target/arm/helper.c b/target/arm/helper.c
28
diff --git a/target/arm/helper.c b/target/arm/helper.c
20
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper.c
30
--- a/target/arm/helper.c
22
+++ b/target/arm/helper.c
31
+++ b/target/arm/helper.c
23
@@ -XXX,XX +XXX,XX @@ static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri,
32
@@ -XXX,XX +XXX,XX @@
24
*/
33
#include "qemu/main-loop.h"
25
int el = arm_current_el(env);
34
#include "qemu/timer.h"
26
35
#include "qemu/bitops.h"
27
- if (el == 0 && !env->cp15.c9_pmuserenr) {
36
-#include "qemu/crc32c.h"
28
+ if (el == 0 && !(env->cp15.c9_pmuserenr & 1)) {
37
#include "qemu/qemu-print.h"
29
return CP_ACCESS_TRAP;
38
#include "exec/exec-all.h"
30
}
39
#include "exec/translation-block.h"
31
if (el < 2 && (env->cp15.mdcr_el2 & MDCR_TPM)
40
-#include <zlib.h> /* for crc32 */
32
@@ -XXX,XX +XXX,XX @@ static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri,
41
#include "hw/irq.h"
33
return CP_ACCESS_OK;
42
#include "system/cpu-timers.h"
43
#include "system/kvm.h"
44
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
45
};
34
}
46
}
35
47
36
+static CPAccessResult pmreg_access_xevcntr(CPUARMState *env,
48
-/*
37
+ const ARMCPRegInfo *ri,
49
- * Note that signed overflow is undefined in C. The following routines are
38
+ bool isread)
50
- * careful to use unsigned types where modulo arithmetic is required.
39
+{
51
- * Failure to do so _will_ break on newer gcc.
40
+ /* ER: event counter read trap control */
52
- */
41
+ if (arm_feature(env, ARM_FEATURE_V8)
53
-
42
+ && arm_current_el(env) == 0
54
-/* Signed saturating arithmetic. */
43
+ && (env->cp15.c9_pmuserenr & (1 << 3)) != 0
55
-
44
+ && isread) {
56
-/* Perform 16-bit signed saturating addition. */
45
+ return CP_ACCESS_OK;
57
-static inline uint16_t add16_sat(uint16_t a, uint16_t b)
46
+ }
58
-{
47
+
59
- uint16_t res;
48
+ return pmreg_access(env, ri, isread);
60
-
49
+}
61
- res = a + b;
50
+
62
- if (((res ^ a) & 0x8000) && !((a ^ b) & 0x8000)) {
51
+static CPAccessResult pmreg_access_swinc(CPUARMState *env,
63
- if (a & 0x8000) {
52
+ const ARMCPRegInfo *ri,
64
- res = 0x8000;
53
+ bool isread)
65
- } else {
54
+{
66
- res = 0x7fff;
55
+ /* SW: software increment write trap control */
67
- }
56
+ if (arm_feature(env, ARM_FEATURE_V8)
68
- }
57
+ && arm_current_el(env) == 0
69
- return res;
58
+ && (env->cp15.c9_pmuserenr & (1 << 1)) != 0
70
-}
59
+ && !isread) {
71
-
60
+ return CP_ACCESS_OK;
72
-/* Perform 8-bit signed saturating addition. */
61
+ }
73
-static inline uint8_t add8_sat(uint8_t a, uint8_t b)
62
+
74
-{
63
+ return pmreg_access(env, ri, isread);
75
- uint8_t res;
64
+}
76
-
65
+
77
- res = a + b;
66
#ifndef CONFIG_USER_ONLY
78
- if (((res ^ a) & 0x80) && !((a ^ b) & 0x80)) {
67
79
- if (a & 0x80) {
68
+static CPAccessResult pmreg_access_selr(CPUARMState *env,
80
- res = 0x80;
69
+ const ARMCPRegInfo *ri,
81
- } else {
70
+ bool isread)
82
- res = 0x7f;
71
+{
83
- }
72
+ /* ER: event counter read trap control */
84
- }
73
+ if (arm_feature(env, ARM_FEATURE_V8)
85
- return res;
74
+ && arm_current_el(env) == 0
86
-}
75
+ && (env->cp15.c9_pmuserenr & (1 << 3)) != 0) {
87
-
76
+ return CP_ACCESS_OK;
88
-/* Perform 16-bit signed saturating subtraction. */
77
+ }
89
-static inline uint16_t sub16_sat(uint16_t a, uint16_t b)
78
+
90
-{
79
+ return pmreg_access(env, ri, isread);
91
- uint16_t res;
80
+}
92
-
81
+
93
- res = a - b;
82
+static CPAccessResult pmreg_access_ccntr(CPUARMState *env,
94
- if (((res ^ a) & 0x8000) && ((a ^ b) & 0x8000)) {
83
+ const ARMCPRegInfo *ri,
95
- if (a & 0x8000) {
84
+ bool isread)
96
- res = 0x8000;
85
+{
97
- } else {
86
+ /* CR: cycle counter read trap control */
98
- res = 0x7fff;
87
+ if (arm_feature(env, ARM_FEATURE_V8)
99
- }
88
+ && arm_current_el(env) == 0
100
- }
89
+ && (env->cp15.c9_pmuserenr & (1 << 2)) != 0
101
- return res;
90
+ && isread) {
102
-}
91
+ return CP_ACCESS_OK;
103
-
92
+ }
104
-/* Perform 8-bit signed saturating subtraction. */
93
+
105
-static inline uint8_t sub8_sat(uint8_t a, uint8_t b)
94
+ return pmreg_access(env, ri, isread);
106
-{
95
+}
107
- uint8_t res;
96
+
108
-
97
static inline bool arm_ccnt_enabled(CPUARMState *env)
109
- res = a - b;
98
{
110
- if (((res ^ a) & 0x80) && ((a ^ b) & 0x80)) {
99
/* This does not support checking PMCCFILTR_EL0 register */
111
- if (a & 0x80) {
100
@@ -XXX,XX +XXX,XX @@ static uint64_t pmxevtyper_read(CPUARMState *env, const ARMCPRegInfo *ri)
112
- res = 0x80;
101
static void pmuserenr_write(CPUARMState *env, const ARMCPRegInfo *ri,
113
- } else {
102
uint64_t value)
114
- res = 0x7f;
103
{
115
- }
104
- env->cp15.c9_pmuserenr = value & 1;
116
- }
105
+ if (arm_feature(env, ARM_FEATURE_V8)) {
117
- return res;
106
+ env->cp15.c9_pmuserenr = value & 0xf;
118
-}
119
-
120
-#define ADD16(a, b, n) RESULT(add16_sat(a, b), n, 16);
121
-#define SUB16(a, b, n) RESULT(sub16_sat(a, b), n, 16);
122
-#define ADD8(a, b, n) RESULT(add8_sat(a, b), n, 8);
123
-#define SUB8(a, b, n) RESULT(sub8_sat(a, b), n, 8);
124
-#define PFX q
125
-
126
-#include "op_addsub.h"
127
-
128
-/* Unsigned saturating arithmetic. */
129
-static inline uint16_t add16_usat(uint16_t a, uint16_t b)
130
-{
131
- uint16_t res;
132
- res = a + b;
133
- if (res < a) {
134
- res = 0xffff;
135
- }
136
- return res;
137
-}
138
-
139
-static inline uint16_t sub16_usat(uint16_t a, uint16_t b)
140
-{
141
- if (a > b) {
142
- return a - b;
143
- } else {
144
- return 0;
145
- }
146
-}
147
-
148
-static inline uint8_t add8_usat(uint8_t a, uint8_t b)
149
-{
150
- uint8_t res;
151
- res = a + b;
152
- if (res < a) {
153
- res = 0xff;
154
- }
155
- return res;
156
-}
157
-
158
-static inline uint8_t sub8_usat(uint8_t a, uint8_t b)
159
-{
160
- if (a > b) {
161
- return a - b;
162
- } else {
163
- return 0;
164
- }
165
-}
166
-
167
-#define ADD16(a, b, n) RESULT(add16_usat(a, b), n, 16);
168
-#define SUB16(a, b, n) RESULT(sub16_usat(a, b), n, 16);
169
-#define ADD8(a, b, n) RESULT(add8_usat(a, b), n, 8);
170
-#define SUB8(a, b, n) RESULT(sub8_usat(a, b), n, 8);
171
-#define PFX uq
172
-
173
-#include "op_addsub.h"
174
-
175
-/* Signed modulo arithmetic. */
176
-#define SARITH16(a, b, n, op) do { \
177
- int32_t sum; \
178
- sum = (int32_t)(int16_t)(a) op (int32_t)(int16_t)(b); \
179
- RESULT(sum, n, 16); \
180
- if (sum >= 0) \
181
- ge |= 3 << (n * 2); \
182
- } while (0)
183
-
184
-#define SARITH8(a, b, n, op) do { \
185
- int32_t sum; \
186
- sum = (int32_t)(int8_t)(a) op (int32_t)(int8_t)(b); \
187
- RESULT(sum, n, 8); \
188
- if (sum >= 0) \
189
- ge |= 1 << n; \
190
- } while (0)
191
-
192
-
193
-#define ADD16(a, b, n) SARITH16(a, b, n, +)
194
-#define SUB16(a, b, n) SARITH16(a, b, n, -)
195
-#define ADD8(a, b, n) SARITH8(a, b, n, +)
196
-#define SUB8(a, b, n) SARITH8(a, b, n, -)
197
-#define PFX s
198
-#define ARITH_GE
199
-
200
-#include "op_addsub.h"
201
-
202
-/* Unsigned modulo arithmetic. */
203
-#define ADD16(a, b, n) do { \
204
- uint32_t sum; \
205
- sum = (uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b); \
206
- RESULT(sum, n, 16); \
207
- if ((sum >> 16) == 1) \
208
- ge |= 3 << (n * 2); \
209
- } while (0)
210
-
211
-#define ADD8(a, b, n) do { \
212
- uint32_t sum; \
213
- sum = (uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b); \
214
- RESULT(sum, n, 8); \
215
- if ((sum >> 8) == 1) \
216
- ge |= 1 << n; \
217
- } while (0)
218
-
219
-#define SUB16(a, b, n) do { \
220
- uint32_t sum; \
221
- sum = (uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b); \
222
- RESULT(sum, n, 16); \
223
- if ((sum >> 16) == 0) \
224
- ge |= 3 << (n * 2); \
225
- } while (0)
226
-
227
-#define SUB8(a, b, n) do { \
228
- uint32_t sum; \
229
- sum = (uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b); \
230
- RESULT(sum, n, 8); \
231
- if ((sum >> 8) == 0) \
232
- ge |= 1 << n; \
233
- } while (0)
234
-
235
-#define PFX u
236
-#define ARITH_GE
237
-
238
-#include "op_addsub.h"
239
-
240
-/* Halved signed arithmetic. */
241
-#define ADD16(a, b, n) \
242
- RESULT(((int32_t)(int16_t)(a) + (int32_t)(int16_t)(b)) >> 1, n, 16)
243
-#define SUB16(a, b, n) \
244
- RESULT(((int32_t)(int16_t)(a) - (int32_t)(int16_t)(b)) >> 1, n, 16)
245
-#define ADD8(a, b, n) \
246
- RESULT(((int32_t)(int8_t)(a) + (int32_t)(int8_t)(b)) >> 1, n, 8)
247
-#define SUB8(a, b, n) \
248
- RESULT(((int32_t)(int8_t)(a) - (int32_t)(int8_t)(b)) >> 1, n, 8)
249
-#define PFX sh
250
-
251
-#include "op_addsub.h"
252
-
253
-/* Halved unsigned arithmetic. */
254
-#define ADD16(a, b, n) \
255
- RESULT(((uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b)) >> 1, n, 16)
256
-#define SUB16(a, b, n) \
257
- RESULT(((uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b)) >> 1, n, 16)
258
-#define ADD8(a, b, n) \
259
- RESULT(((uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b)) >> 1, n, 8)
260
-#define SUB8(a, b, n) \
261
- RESULT(((uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b)) >> 1, n, 8)
262
-#define PFX uh
263
-
264
-#include "op_addsub.h"
265
-
266
-static inline uint8_t do_usad(uint8_t a, uint8_t b)
267
-{
268
- if (a > b) {
269
- return a - b;
270
- } else {
271
- return b - a;
272
- }
273
-}
274
-
275
-/* Unsigned sum of absolute byte differences. */
276
-uint32_t HELPER(usad8)(uint32_t a, uint32_t b)
277
-{
278
- uint32_t sum;
279
- sum = do_usad(a, b);
280
- sum += do_usad(a >> 8, b >> 8);
281
- sum += do_usad(a >> 16, b >> 16);
282
- sum += do_usad(a >> 24, b >> 24);
283
- return sum;
284
-}
285
-
286
-/* For ARMv6 SEL instruction. */
287
-uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b)
288
-{
289
- uint32_t mask;
290
-
291
- mask = 0;
292
- if (flags & 1) {
293
- mask |= 0xff;
294
- }
295
- if (flags & 2) {
296
- mask |= 0xff00;
297
- }
298
- if (flags & 4) {
299
- mask |= 0xff0000;
300
- }
301
- if (flags & 8) {
302
- mask |= 0xff000000;
303
- }
304
- return (a & mask) | (b & ~mask);
305
-}
306
-
307
-/*
308
- * CRC helpers.
309
- * The upper bytes of val (above the number specified by 'bytes') must have
310
- * been zeroed out by the caller.
311
- */
312
-uint32_t HELPER(crc32)(uint32_t acc, uint32_t val, uint32_t bytes)
313
-{
314
- uint8_t buf[4];
315
-
316
- stl_le_p(buf, val);
317
-
318
- /* zlib crc32 converts the accumulator and output to one's complement. */
319
- return crc32(acc ^ 0xffffffff, buf, bytes) ^ 0xffffffff;
320
-}
321
-
322
-uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
323
-{
324
- uint8_t buf[4];
325
-
326
- stl_le_p(buf, val);
327
-
328
- /* Linux crc32c converts the output to one's complement. */
329
- return crc32c(acc, buf, bytes) ^ 0xffffffff;
330
-}
331
332
/*
333
* Return the exception level to which FP-disabled exceptions should
334
diff --git a/target/arm/tcg/arith_helper.c b/target/arm/tcg/arith_helper.c
335
new file mode 100644
336
index XXXXXXX..XXXXXXX
337
--- /dev/null
338
+++ b/target/arm/tcg/arith_helper.c
339
@@ -XXX,XX +XXX,XX @@
340
+/*
341
+ * ARM generic helpers for various arithmetical operations.
342
+ *
343
+ * This code is licensed under the GNU GPL v2 or later.
344
+ *
345
+ * SPDX-License-Identifier: GPL-2.0-or-later
346
+ */
347
+#include "qemu/osdep.h"
348
+#include "cpu.h"
349
+#include "exec/helper-proto.h"
350
+#include "qemu/crc32c.h"
351
+#include <zlib.h> /* for crc32 */
352
+
353
+/*
354
+ * Note that signed overflow is undefined in C. The following routines are
355
+ * careful to use unsigned types where modulo arithmetic is required.
356
+ * Failure to do so _will_ break on newer gcc.
357
+ */
358
+
359
+/* Signed saturating arithmetic. */
360
+
361
+/* Perform 16-bit signed saturating addition. */
362
+static inline uint16_t add16_sat(uint16_t a, uint16_t b)
363
+{
364
+ uint16_t res;
365
+
366
+ res = a + b;
367
+ if (((res ^ a) & 0x8000) && !((a ^ b) & 0x8000)) {
368
+ if (a & 0x8000) {
369
+ res = 0x8000;
370
+ } else {
371
+ res = 0x7fff;
372
+ }
373
+ }
374
+ return res;
375
+}
376
+
377
+/* Perform 8-bit signed saturating addition. */
378
+static inline uint8_t add8_sat(uint8_t a, uint8_t b)
379
+{
380
+ uint8_t res;
381
+
382
+ res = a + b;
383
+ if (((res ^ a) & 0x80) && !((a ^ b) & 0x80)) {
384
+ if (a & 0x80) {
385
+ res = 0x80;
386
+ } else {
387
+ res = 0x7f;
388
+ }
389
+ }
390
+ return res;
391
+}
392
+
393
+/* Perform 16-bit signed saturating subtraction. */
394
+static inline uint16_t sub16_sat(uint16_t a, uint16_t b)
395
+{
396
+ uint16_t res;
397
+
398
+ res = a - b;
399
+ if (((res ^ a) & 0x8000) && ((a ^ b) & 0x8000)) {
400
+ if (a & 0x8000) {
401
+ res = 0x8000;
402
+ } else {
403
+ res = 0x7fff;
404
+ }
405
+ }
406
+ return res;
407
+}
408
+
409
+/* Perform 8-bit signed saturating subtraction. */
410
+static inline uint8_t sub8_sat(uint8_t a, uint8_t b)
411
+{
412
+ uint8_t res;
413
+
414
+ res = a - b;
415
+ if (((res ^ a) & 0x80) && ((a ^ b) & 0x80)) {
416
+ if (a & 0x80) {
417
+ res = 0x80;
418
+ } else {
419
+ res = 0x7f;
420
+ }
421
+ }
422
+ return res;
423
+}
424
+
425
+#define ADD16(a, b, n) RESULT(add16_sat(a, b), n, 16);
426
+#define SUB16(a, b, n) RESULT(sub16_sat(a, b), n, 16);
427
+#define ADD8(a, b, n) RESULT(add8_sat(a, b), n, 8);
428
+#define SUB8(a, b, n) RESULT(sub8_sat(a, b), n, 8);
429
+#define PFX q
430
+
431
+#include "op_addsub.c.inc"
432
+
433
+/* Unsigned saturating arithmetic. */
434
+static inline uint16_t add16_usat(uint16_t a, uint16_t b)
435
+{
436
+ uint16_t res;
437
+ res = a + b;
438
+ if (res < a) {
439
+ res = 0xffff;
440
+ }
441
+ return res;
442
+}
443
+
444
+static inline uint16_t sub16_usat(uint16_t a, uint16_t b)
445
+{
446
+ if (a > b) {
447
+ return a - b;
107
+ } else {
448
+ } else {
108
+ env->cp15.c9_pmuserenr = value & 1;
449
+ return 0;
109
+ }
450
+ }
110
}
451
+}
111
452
+
112
static void pmintenset_write(CPUARMState *env, const ARMCPRegInfo *ri,
453
+static inline uint8_t add8_usat(uint8_t a, uint8_t b)
113
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
454
+{
114
.raw_writefn = raw_write },
455
+ uint8_t res;
115
/* Unimplemented so WI. */
456
+ res = a + b;
116
{ .name = "PMSWINC", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 4,
457
+ if (res < a) {
117
- .access = PL0_W, .accessfn = pmreg_access, .type = ARM_CP_NOP },
458
+ res = 0xff;
118
+ .access = PL0_W, .accessfn = pmreg_access_swinc, .type = ARM_CP_NOP },
459
+ }
119
#ifndef CONFIG_USER_ONLY
460
+ return res;
120
{ .name = "PMSELR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 5,
461
+}
121
.access = PL0_RW, .type = ARM_CP_ALIAS,
462
+
122
.fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmselr),
463
+static inline uint8_t sub8_usat(uint8_t a, uint8_t b)
123
- .accessfn = pmreg_access, .writefn = pmselr_write,
464
+{
124
+ .accessfn = pmreg_access_selr, .writefn = pmselr_write,
465
+ if (a > b) {
125
.raw_writefn = raw_write},
466
+ return a - b;
126
{ .name = "PMSELR_EL0", .state = ARM_CP_STATE_AA64,
467
+ } else {
127
.opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 5,
468
+ return 0;
128
- .access = PL0_RW, .accessfn = pmreg_access,
469
+ }
129
+ .access = PL0_RW, .accessfn = pmreg_access_selr,
470
+}
130
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmselr),
471
+
131
.writefn = pmselr_write, .raw_writefn = raw_write, },
472
+#define ADD16(a, b, n) RESULT(add16_usat(a, b), n, 16);
132
{ .name = "PMCCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 0,
473
+#define SUB16(a, b, n) RESULT(sub16_usat(a, b), n, 16);
133
.access = PL0_RW, .resetvalue = 0, .type = ARM_CP_IO,
474
+#define ADD8(a, b, n) RESULT(add8_usat(a, b), n, 8);
134
.readfn = pmccntr_read, .writefn = pmccntr_write32,
475
+#define SUB8(a, b, n) RESULT(sub8_usat(a, b), n, 8);
135
- .accessfn = pmreg_access },
476
+#define PFX uq
136
+ .accessfn = pmreg_access_ccntr },
477
+
137
{ .name = "PMCCNTR_EL0", .state = ARM_CP_STATE_AA64,
478
+#include "op_addsub.c.inc"
138
.opc0 = 3, .opc1 = 3, .crn = 9, .crm = 13, .opc2 = 0,
479
+
139
- .access = PL0_RW, .accessfn = pmreg_access,
480
+/* Signed modulo arithmetic. */
140
+ .access = PL0_RW, .accessfn = pmreg_access_ccntr,
481
+#define SARITH16(a, b, n, op) do { \
141
.type = ARM_CP_IO,
482
+ int32_t sum; \
142
.readfn = pmccntr_read, .writefn = pmccntr_write, },
483
+ sum = (int32_t)(int16_t)(a) op (int32_t)(int16_t)(b); \
143
#endif
484
+ RESULT(sum, n, 16); \
144
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
485
+ if (sum >= 0) \
145
/* Unimplemented, RAZ/WI. */
486
+ ge |= 3 << (n * 2); \
146
{ .name = "PMXEVCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 2,
487
+ } while (0)
147
.access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0,
488
+
148
- .accessfn = pmreg_access },
489
+#define SARITH8(a, b, n, op) do { \
149
+ .accessfn = pmreg_access_xevcntr },
490
+ int32_t sum; \
150
{ .name = "PMUSERENR", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 0,
491
+ sum = (int32_t)(int8_t)(a) op (int32_t)(int8_t)(b); \
151
.access = PL0_R | PL1_RW, .accessfn = access_tpm,
492
+ RESULT(sum, n, 8); \
152
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmuserenr),
493
+ if (sum >= 0) \
494
+ ge |= 1 << n; \
495
+ } while (0)
496
+
497
+
498
+#define ADD16(a, b, n) SARITH16(a, b, n, +)
499
+#define SUB16(a, b, n) SARITH16(a, b, n, -)
500
+#define ADD8(a, b, n) SARITH8(a, b, n, +)
501
+#define SUB8(a, b, n) SARITH8(a, b, n, -)
502
+#define PFX s
503
+#define ARITH_GE
504
+
505
+#include "op_addsub.c.inc"
506
+
507
+/* Unsigned modulo arithmetic. */
508
+#define ADD16(a, b, n) do { \
509
+ uint32_t sum; \
510
+ sum = (uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b); \
511
+ RESULT(sum, n, 16); \
512
+ if ((sum >> 16) == 1) \
513
+ ge |= 3 << (n * 2); \
514
+ } while (0)
515
+
516
+#define ADD8(a, b, n) do { \
517
+ uint32_t sum; \
518
+ sum = (uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b); \
519
+ RESULT(sum, n, 8); \
520
+ if ((sum >> 8) == 1) \
521
+ ge |= 1 << n; \
522
+ } while (0)
523
+
524
+#define SUB16(a, b, n) do { \
525
+ uint32_t sum; \
526
+ sum = (uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b); \
527
+ RESULT(sum, n, 16); \
528
+ if ((sum >> 16) == 0) \
529
+ ge |= 3 << (n * 2); \
530
+ } while (0)
531
+
532
+#define SUB8(a, b, n) do { \
533
+ uint32_t sum; \
534
+ sum = (uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b); \
535
+ RESULT(sum, n, 8); \
536
+ if ((sum >> 8) == 0) \
537
+ ge |= 1 << n; \
538
+ } while (0)
539
+
540
+#define PFX u
541
+#define ARITH_GE
542
+
543
+#include "op_addsub.c.inc"
544
+
545
+/* Halved signed arithmetic. */
546
+#define ADD16(a, b, n) \
547
+ RESULT(((int32_t)(int16_t)(a) + (int32_t)(int16_t)(b)) >> 1, n, 16)
548
+#define SUB16(a, b, n) \
549
+ RESULT(((int32_t)(int16_t)(a) - (int32_t)(int16_t)(b)) >> 1, n, 16)
550
+#define ADD8(a, b, n) \
551
+ RESULT(((int32_t)(int8_t)(a) + (int32_t)(int8_t)(b)) >> 1, n, 8)
552
+#define SUB8(a, b, n) \
553
+ RESULT(((int32_t)(int8_t)(a) - (int32_t)(int8_t)(b)) >> 1, n, 8)
554
+#define PFX sh
555
+
556
+#include "op_addsub.c.inc"
557
+
558
+/* Halved unsigned arithmetic. */
559
+#define ADD16(a, b, n) \
560
+ RESULT(((uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b)) >> 1, n, 16)
561
+#define SUB16(a, b, n) \
562
+ RESULT(((uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b)) >> 1, n, 16)
563
+#define ADD8(a, b, n) \
564
+ RESULT(((uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b)) >> 1, n, 8)
565
+#define SUB8(a, b, n) \
566
+ RESULT(((uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b)) >> 1, n, 8)
567
+#define PFX uh
568
+
569
+#include "op_addsub.c.inc"
570
+
571
+static inline uint8_t do_usad(uint8_t a, uint8_t b)
572
+{
573
+ if (a > b) {
574
+ return a - b;
575
+ } else {
576
+ return b - a;
577
+ }
578
+}
579
+
580
+/* Unsigned sum of absolute byte differences. */
581
+uint32_t HELPER(usad8)(uint32_t a, uint32_t b)
582
+{
583
+ uint32_t sum;
584
+ sum = do_usad(a, b);
585
+ sum += do_usad(a >> 8, b >> 8);
586
+ sum += do_usad(a >> 16, b >> 16);
587
+ sum += do_usad(a >> 24, b >> 24);
588
+ return sum;
589
+}
590
+
591
+/* For ARMv6 SEL instruction. */
592
+uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b)
593
+{
594
+ uint32_t mask;
595
+
596
+ mask = 0;
597
+ if (flags & 1) {
598
+ mask |= 0xff;
599
+ }
600
+ if (flags & 2) {
601
+ mask |= 0xff00;
602
+ }
603
+ if (flags & 4) {
604
+ mask |= 0xff0000;
605
+ }
606
+ if (flags & 8) {
607
+ mask |= 0xff000000;
608
+ }
609
+ return (a & mask) | (b & ~mask);
610
+}
611
+
612
+/*
613
+ * CRC helpers.
614
+ * The upper bytes of val (above the number specified by 'bytes') must have
615
+ * been zeroed out by the caller.
616
+ */
617
+uint32_t HELPER(crc32)(uint32_t acc, uint32_t val, uint32_t bytes)
618
+{
619
+ uint8_t buf[4];
620
+
621
+ stl_le_p(buf, val);
622
+
623
+ /* zlib crc32 converts the accumulator and output to one's complement. */
624
+ return crc32(acc ^ 0xffffffff, buf, bytes) ^ 0xffffffff;
625
+}
626
+
627
+uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
628
+{
629
+ uint8_t buf[4];
630
+
631
+ stl_le_p(buf, val);
632
+
633
+ /* Linux crc32c converts the output to one's complement. */
634
+ return crc32c(acc, buf, bytes) ^ 0xffffffff;
635
+}
636
diff --git a/target/arm/op_addsub.h b/target/arm/tcg/op_addsub.c.inc
637
similarity index 100%
638
rename from target/arm/op_addsub.h
639
rename to target/arm/tcg/op_addsub.c.inc
640
diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build
641
index XXXXXXX..XXXXXXX 100644
642
--- a/target/arm/tcg/meson.build
643
+++ b/target/arm/tcg/meson.build
644
@@ -XXX,XX +XXX,XX @@ arm_ss.add(files(
645
'tlb_helper.c',
646
'vec_helper.c',
647
'tlb-insns.c',
648
+ 'arith_helper.c',
649
))
650
651
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
153
--
652
--
154
2.7.4
653
2.34.1
155
654
156
655
diff view generated by jsdifflib
New patch
1
From: Pierrick Bouvier <pierrick.bouvier@linaro.org>
1
2
3
Before changing default pauth algorithm, we need to make sure current
4
default one (QARMA5) can still be selected.
5
6
$ qemu-system-aarch64 -cpu max,pauth-qarma5=on ...
7
8
Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20241219183211.3493974-2-pierrick.bouvier@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
docs/system/arm/cpu-features.rst | 5 ++++-
14
target/arm/cpu.h | 1 +
15
target/arm/arm-qmp-cmds.c | 2 +-
16
target/arm/cpu64.c | 20 ++++++++++++++------
17
tests/qtest/arm-cpu-features.c | 15 +++++++++++----
18
5 files changed, 31 insertions(+), 12 deletions(-)
19
20
diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst
21
index XXXXXXX..XXXXXXX 100644
22
--- a/docs/system/arm/cpu-features.rst
23
+++ b/docs/system/arm/cpu-features.rst
24
@@ -XXX,XX +XXX,XX @@ Below is the list of TCG VCPU features and their descriptions.
25
``pauth-qarma3``
26
When ``pauth`` is enabled, select the architected QARMA3 algorithm.
27
28
-Without either ``pauth-impdef`` or ``pauth-qarma3`` enabled,
29
+``pauth-qarma5``
30
+ When ``pauth`` is enabled, select the architected QARMA5 algorithm.
31
+
32
+Without ``pauth-impdef``, ``pauth-qarma3`` or ``pauth-qarma5`` enabled,
33
the architected QARMA5 algorithm is used. The architected QARMA5
34
and QARMA3 algorithms have good cryptographic properties, but can
35
be quite slow to emulate. The impdef algorithm used by QEMU is
36
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/cpu.h
39
+++ b/target/arm/cpu.h
40
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
41
bool prop_pauth;
42
bool prop_pauth_impdef;
43
bool prop_pauth_qarma3;
44
+ bool prop_pauth_qarma5;
45
bool prop_lpa2;
46
47
/* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
48
diff --git a/target/arm/arm-qmp-cmds.c b/target/arm/arm-qmp-cmds.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/arm-qmp-cmds.c
51
+++ b/target/arm/arm-qmp-cmds.c
52
@@ -XXX,XX +XXX,XX @@ static const char *cpu_model_advertised_features[] = {
53
"sve640", "sve768", "sve896", "sve1024", "sve1152", "sve1280",
54
"sve1408", "sve1536", "sve1664", "sve1792", "sve1920", "sve2048",
55
"kvm-no-adjvtime", "kvm-steal-time",
56
- "pauth", "pauth-impdef", "pauth-qarma3",
57
+ "pauth", "pauth-impdef", "pauth-qarma3", "pauth-qarma5",
58
NULL
59
};
60
61
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/cpu64.c
64
+++ b/target/arm/cpu64.c
65
@@ -XXX,XX +XXX,XX @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
66
}
67
68
if (cpu->prop_pauth) {
69
- if (cpu->prop_pauth_impdef && cpu->prop_pauth_qarma3) {
70
+ if ((cpu->prop_pauth_impdef && cpu->prop_pauth_qarma3) ||
71
+ (cpu->prop_pauth_impdef && cpu->prop_pauth_qarma5) ||
72
+ (cpu->prop_pauth_qarma3 && cpu->prop_pauth_qarma5)) {
73
error_setg(errp,
74
- "cannot enable both pauth-impdef and pauth-qarma3");
75
+ "cannot enable pauth-impdef, pauth-qarma3 and "
76
+ "pauth-qarma5 at the same time");
77
return;
78
}
79
80
@@ -XXX,XX +XXX,XX @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
81
} else if (cpu->prop_pauth_qarma3) {
82
isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, APA3, features);
83
isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, GPA3, 1);
84
- } else {
85
+ } else { /* default is pauth-qarma5 */
86
isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, APA, features);
87
isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPA, 1);
88
}
89
- } else if (cpu->prop_pauth_impdef || cpu->prop_pauth_qarma3) {
90
- error_setg(errp, "cannot enable pauth-impdef or "
91
- "pauth-qarma3 without pauth");
92
+ } else if (cpu->prop_pauth_impdef ||
93
+ cpu->prop_pauth_qarma3 ||
94
+ cpu->prop_pauth_qarma5) {
95
+ error_setg(errp, "cannot enable pauth-impdef, pauth-qarma3 or "
96
+ "pauth-qarma5 without pauth");
97
error_append_hint(errp, "Add pauth=on to the CPU property list.\n");
98
}
99
}
100
@@ -XXX,XX +XXX,XX @@ static const Property arm_cpu_pauth_impdef_property =
101
DEFINE_PROP_BOOL("pauth-impdef", ARMCPU, prop_pauth_impdef, false);
102
static const Property arm_cpu_pauth_qarma3_property =
103
DEFINE_PROP_BOOL("pauth-qarma3", ARMCPU, prop_pauth_qarma3, false);
104
+static Property arm_cpu_pauth_qarma5_property =
105
+ DEFINE_PROP_BOOL("pauth-qarma5", ARMCPU, prop_pauth_qarma5, false);
106
107
void aarch64_add_pauth_properties(Object *obj)
108
{
109
@@ -XXX,XX +XXX,XX @@ void aarch64_add_pauth_properties(Object *obj)
110
} else {
111
qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_impdef_property);
112
qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_qarma3_property);
113
+ qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_qarma5_property);
114
}
115
}
116
117
diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/tests/qtest/arm-cpu-features.c
120
+++ b/tests/qtest/arm-cpu-features.c
121
@@ -XXX,XX +XXX,XX @@ static void pauth_tests_default(QTestState *qts, const char *cpu_type)
122
assert_has_feature_enabled(qts, cpu_type, "pauth");
123
assert_has_feature_disabled(qts, cpu_type, "pauth-impdef");
124
assert_has_feature_disabled(qts, cpu_type, "pauth-qarma3");
125
+ assert_has_feature_disabled(qts, cpu_type, "pauth-qarma5");
126
assert_set_feature(qts, cpu_type, "pauth", false);
127
assert_set_feature(qts, cpu_type, "pauth", true);
128
assert_set_feature(qts, cpu_type, "pauth-impdef", true);
129
assert_set_feature(qts, cpu_type, "pauth-impdef", false);
130
assert_set_feature(qts, cpu_type, "pauth-qarma3", true);
131
assert_set_feature(qts, cpu_type, "pauth-qarma3", false);
132
+ assert_set_feature(qts, cpu_type, "pauth-qarma5", true);
133
+ assert_set_feature(qts, cpu_type, "pauth-qarma5", false);
134
assert_error(qts, cpu_type,
135
- "cannot enable pauth-impdef or pauth-qarma3 without pauth",
136
+ "cannot enable pauth-impdef, pauth-qarma3 or pauth-qarma5 without pauth",
137
"{ 'pauth': false, 'pauth-impdef': true }");
138
assert_error(qts, cpu_type,
139
- "cannot enable pauth-impdef or pauth-qarma3 without pauth",
140
+ "cannot enable pauth-impdef, pauth-qarma3 or pauth-qarma5 without pauth",
141
"{ 'pauth': false, 'pauth-qarma3': true }");
142
assert_error(qts, cpu_type,
143
- "cannot enable both pauth-impdef and pauth-qarma3",
144
- "{ 'pauth': true, 'pauth-impdef': true, 'pauth-qarma3': true }");
145
+ "cannot enable pauth-impdef, pauth-qarma3 or pauth-qarma5 without pauth",
146
+ "{ 'pauth': false, 'pauth-qarma5': true }");
147
+ assert_error(qts, cpu_type,
148
+ "cannot enable pauth-impdef, pauth-qarma3 and pauth-qarma5 at the same time",
149
+ "{ 'pauth': true, 'pauth-impdef': true, 'pauth-qarma3': true,"
150
+ " 'pauth-qarma5': true }");
151
}
152
153
static void test_query_cpu_model_expansion(const void *data)
154
--
155
2.34.1
diff view generated by jsdifflib
New patch
1
The pauth-3 test explicitly tests that a computation of the
2
pointer-authentication produces the expected result. This means that
3
it must be run with the QARMA5 algorithm.
1
4
5
Explicitly set the pauth algorithm when running this test, so that it
6
doesn't break when we change the default algorithm the 'max' CPU
7
uses.
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
tests/tcg/aarch64/Makefile.softmmu-target | 3 +++
12
1 file changed, 3 insertions(+)
13
14
diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/tcg/aarch64/Makefile.softmmu-target
17
+++ b/tests/tcg/aarch64/Makefile.softmmu-target
18
@@ -XXX,XX +XXX,XX @@ EXTRA_RUNS+=run-memory-replay
19
20
ifneq ($(CROSS_CC_HAS_ARMV8_3),)
21
pauth-3: CFLAGS += $(CROSS_CC_HAS_ARMV8_3)
22
+# This test explicitly checks the output of the pauth operation so we
23
+# must force the use of the QARMA5 algorithm for it.
24
+run-pauth-3: QEMU_BASE_MACHINE=-M virt -cpu max,pauth-qarma5=on -display none
25
else
26
pauth-3:
27
    $(call skip-test, "BUILD of $@", "missing compiler support")
28
--
29
2.34.1
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Pierrick Bouvier <pierrick.bouvier@linaro.org>
2
2
3
The power state spec section 5.1.5 AFFINITY_INFO defines the
3
Pointer authentication on aarch64 is pretty expensive (up to 50% of
4
affinity info return values as
4
execution time) when running a virtual machine with tcg and -cpu max
5
(which enables pauth=on).
5
6
6
0 ON
7
The advice is always: use pauth-impdef=on.
7
1 OFF
8
Our documentation even mentions it "by default" in
8
2 ON_PENDING
9
docs/system/introduction.rst.
9
10
10
I grepped QEMU for power_state to ensure that no assumptions
11
Thus, we change the default to use impdef by default. This does not
11
of OFF=0 were being made.
12
affect kvm or hvf acceleration, since pauth algorithm used is the one
13
from host cpu.
12
14
13
Signed-off-by: Andrew Jones <drjones@redhat.com>
15
This change is retro compatible, in terms of cli, with previous
14
Message-id: 20170303123232.4967-1-drjones@redhat.com
16
versions, as the semantic of using -cpu max,pauth-impdef=on, and -cpu
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
max,pauth-qarma3=on is preserved.
18
The new option introduced in previous patch and matching old default is
19
-cpu max,pauth-qarma5=on.
20
It is retro compatible with migration as well, by defining a backcompat
21
property, that will use qarma5 by default for virt machine <= 9.2.
22
Tested by saving and restoring a vm from qemu 9.2.0 into qemu-master
23
(10.0) for cpus neoverse-n2 and max.
24
25
Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Message-id: 20241219183211.3493974-3-pierrick.bouvier@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
29
---
18
target/arm/cpu.h | 4 ++--
30
docs/system/arm/cpu-features.rst | 2 +-
19
1 file changed, 2 insertions(+), 2 deletions(-)
31
docs/system/introduction.rst | 2 +-
32
target/arm/cpu.h | 3 +++
33
hw/core/machine.c | 4 +++-
34
target/arm/cpu.c | 2 ++
35
target/arm/cpu64.c | 22 ++++++++++++++++------
36
6 files changed, 26 insertions(+), 9 deletions(-)
20
37
38
diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst
39
index XXXXXXX..XXXXXXX 100644
40
--- a/docs/system/arm/cpu-features.rst
41
+++ b/docs/system/arm/cpu-features.rst
42
@@ -XXX,XX +XXX,XX @@ Below is the list of TCG VCPU features and their descriptions.
43
When ``pauth`` is enabled, select the architected QARMA5 algorithm.
44
45
Without ``pauth-impdef``, ``pauth-qarma3`` or ``pauth-qarma5`` enabled,
46
-the architected QARMA5 algorithm is used. The architected QARMA5
47
+the QEMU impdef algorithm is used. The architected QARMA5
48
and QARMA3 algorithms have good cryptographic properties, but can
49
be quite slow to emulate. The impdef algorithm used by QEMU is
50
non-cryptographic but significantly faster.
51
diff --git a/docs/system/introduction.rst b/docs/system/introduction.rst
52
index XXXXXXX..XXXXXXX 100644
53
--- a/docs/system/introduction.rst
54
+++ b/docs/system/introduction.rst
55
@@ -XXX,XX +XXX,XX @@ would default to it anyway.
56
57
.. code::
58
59
- -cpu max,pauth-impdef=on \
60
+ -cpu max \
61
-smp 4 \
62
-accel tcg \
63
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
64
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
22
index XXXXXXX..XXXXXXX 100644
65
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu.h
66
--- a/target/arm/cpu.h
24
+++ b/target/arm/cpu.h
67
+++ b/target/arm/cpu.h
25
@@ -XXX,XX +XXX,XX @@ typedef void ARMELChangeHook(ARMCPU *cpu, void *opaque);
68
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
26
/* These values map onto the return values for
69
/* QOM property to indicate we should use the back-compat CNTFRQ default */
27
* QEMU_PSCI_0_2_FN_AFFINITY_INFO */
70
bool backcompat_cntfrq;
28
typedef enum ARMPSCIState {
71
29
- PSCI_OFF = 0,
72
+ /* QOM property to indicate we should use the back-compat QARMA5 default */
30
- PSCI_ON = 1,
73
+ bool backcompat_pauth_default_use_qarma5;
31
+ PSCI_ON = 0,
74
+
32
+ PSCI_OFF = 1,
75
/* Specify the number of cores in this CPU cluster. Used for the L2CTLR
33
PSCI_ON_PENDING = 2
76
* register.
34
} ARMPSCIState;
77
*/
35
78
diff --git a/hw/core/machine.c b/hw/core/machine.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/hw/core/machine.c
81
+++ b/hw/core/machine.c
82
@@ -XXX,XX +XXX,XX @@
83
#include "hw/virtio/virtio-iommu.h"
84
#include "audio/audio.h"
85
86
-GlobalProperty hw_compat_9_2[] = {};
87
+GlobalProperty hw_compat_9_2[] = {
88
+ {"arm-cpu", "backcompat-pauth-default-use-qarma5", "true"},
89
+};
90
const size_t hw_compat_9_2_len = G_N_ELEMENTS(hw_compat_9_2);
91
92
GlobalProperty hw_compat_9_1[] = {
93
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/cpu.c
96
+++ b/target/arm/cpu.c
97
@@ -XXX,XX +XXX,XX @@ static const Property arm_cpu_properties[] = {
98
DEFINE_PROP_INT32("core-count", ARMCPU, core_count, -1),
99
/* True to default to the backward-compat old CNTFRQ rather than 1Ghz */
100
DEFINE_PROP_BOOL("backcompat-cntfrq", ARMCPU, backcompat_cntfrq, false),
101
+ DEFINE_PROP_BOOL("backcompat-pauth-default-use-qarma5", ARMCPU,
102
+ backcompat_pauth_default_use_qarma5, false),
103
};
104
105
static const gchar *arm_gdb_arch_name(CPUState *cs)
106
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/target/arm/cpu64.c
109
+++ b/target/arm/cpu64.c
110
@@ -XXX,XX +XXX,XX @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
111
return;
112
}
113
114
- if (cpu->prop_pauth_impdef) {
115
- isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, API, features);
116
- isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPI, 1);
117
+ bool use_default = !cpu->prop_pauth_qarma5 &&
118
+ !cpu->prop_pauth_qarma3 &&
119
+ !cpu->prop_pauth_impdef;
120
+
121
+ if (cpu->prop_pauth_qarma5 ||
122
+ (use_default &&
123
+ cpu->backcompat_pauth_default_use_qarma5)) {
124
+ isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, APA, features);
125
+ isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPA, 1);
126
} else if (cpu->prop_pauth_qarma3) {
127
isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, APA3, features);
128
isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, GPA3, 1);
129
- } else { /* default is pauth-qarma5 */
130
- isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, APA, features);
131
- isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPA, 1);
132
+ } else if (cpu->prop_pauth_impdef ||
133
+ (use_default &&
134
+ !cpu->backcompat_pauth_default_use_qarma5)) {
135
+ isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, API, features);
136
+ isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPI, 1);
137
+ } else {
138
+ g_assert_not_reached();
139
}
140
} else if (cpu->prop_pauth_impdef ||
141
cpu->prop_pauth_qarma3 ||
36
--
142
--
37
2.7.4
143
2.34.1
38
39
diff view generated by jsdifflib
New patch
1
From: Pierrick Bouvier <pierrick.bouvier@linaro.org>
1
2
3
Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
4
Message-id: 20241219183211.3493974-4-pierrick.bouvier@linaro.org
5
[PMM: Removed a paragraph about using non-versioned models.]
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
docs/system/arm/virt.rst | 4 ++++
9
1 file changed, 4 insertions(+)
10
11
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
12
index XXXXXXX..XXXXXXX 100644
13
--- a/docs/system/arm/virt.rst
14
+++ b/docs/system/arm/virt.rst
15
@@ -XXX,XX +XXX,XX @@ of the 5.0 release and ``virt-5.0`` of the 5.1 release. Migration
16
is not guaranteed to work between different QEMU releases for
17
the non-versioned ``virt`` machine type.
18
19
+VM migration is not guaranteed when using ``-cpu max``, as features
20
+supported may change between QEMU versions. To ensure your VM can be
21
+migrated, it is recommended to use another cpu model instead.
22
+
23
Supported devices
24
"""""""""""""""""
25
26
--
27
2.34.1
diff view generated by jsdifflib