From 906853e1427a1ff89c64c0ebb6faa9c68f0a5d74 Mon Sep 17 00:00:00 2001 From: Anastasia Belova Date: Mon, 13 Jan 2025 12:35:32 +0000 Subject: [PATCH 01/11] hw/arm_sysctl: fix extracting 31th bit of val 1 << 31 is casted to uint64_t while bitwise and with val. So this value may become 0xffffffff80000000 but only 31th "start" bit is required. This is not possible in practice because the MemoryRegionOps uses the default max access size of 4 bytes and so none of the upper bytes of val will be set, but the bitfield extract API is clearer anyway. Use the bitfield extract() API instead. Found by Linux Verification Center (linuxtesting.org) with SVACE. Signed-off-by: Anastasia Belova Message-id: 20241220125429.7552-1-abelova@astralinux.ru Reviewed-by: Peter Maydell [PMM: add clarification to commit message] Signed-off-by: Peter Maydell --- hw/misc/arm_sysctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/misc/arm_sysctl.c b/hw/misc/arm_sysctl.c index 016a302e67..01663407ec 100644 --- a/hw/misc/arm_sysctl.c +++ b/hw/misc/arm_sysctl.c @@ -520,7 +520,7 @@ static void arm_sysctl_write(void *opaque, hwaddr offset, * as zero. */ s->sys_cfgctrl = val & ~((3 << 18) | (1 << 31)); - if (val & (1 << 31)) { + if (extract64(val, 31, 1)) { /* Start bit set -- actually do something */ unsigned int dcc = extract32(s->sys_cfgctrl, 26, 4); unsigned int function = extract32(s->sys_cfgctrl, 20, 6); From 593b910ebedb9f8969aba22ca35970f710722ba7 Mon Sep 17 00:00:00 2001 From: Tigran Sogomonian Date: Mon, 13 Jan 2025 12:35:32 +0000 Subject: [PATCH 02/11] hw/misc: cast rpm to uint64_t The value of an arithmetic expression 'rpm * NPCM7XX_MFT_PULSE_PER_REVOLUTION' is a subject to overflow because its operands are not cast to a larger data type before performing arithmetic. Thus, need to cast rpm to uint64_t. Found by Linux Verification Center (linuxtesting.org) with SVACE. Signed-off-by: Tigran Sogomonian Reviewed-by: Patrick Leis Reviewed-by: Hao Wu Message-id: 20241226130311.1349-1-tsogomonian@astralinux.ru Signed-off-by: Peter Maydell --- hw/misc/npcm7xx_mft.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/misc/npcm7xx_mft.c b/hw/misc/npcm7xx_mft.c index 9fcc69fe5c..e565cac05d 100644 --- a/hw/misc/npcm7xx_mft.c +++ b/hw/misc/npcm7xx_mft.c @@ -172,8 +172,9 @@ static NPCM7xxMFTCaptureState npcm7xx_mft_compute_cnt( * RPM = revolution/min. The time for one revlution (in ns) is * MINUTE_TO_NANOSECOND / RPM. */ - count = clock_ns_to_ticks(clock, (60 * NANOSECONDS_PER_SECOND) / - (rpm * NPCM7XX_MFT_PULSE_PER_REVOLUTION)); + count = clock_ns_to_ticks(clock, + (uint64_t)(60 * NANOSECONDS_PER_SECOND) / + ((uint64_t)rpm * NPCM7XX_MFT_PULSE_PER_REVOLUTION)); } if (count > NPCM7XX_MFT_MAX_CNT) { From 16e8c947bd6f741d328bb1521f62f69dccaa3fe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 13 Jan 2025 12:35:33 +0000 Subject: [PATCH 03/11] tests/qtest/boot-serial-test: Improve ASM comments of PL011 tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re-indent ASM comments adding the 'loop:' label. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Fabiano Rosas Signed-off-by: Peter Maydell --- tests/qtest/boot-serial-test.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c index 3b92fa5d50..a71d285780 100644 --- a/tests/qtest/boot-serial-test.c +++ b/tests/qtest/boot-serial-test.c @@ -70,18 +70,18 @@ static const uint8_t kernel_plml605[] = { }; static const uint8_t bios_raspi2[] = { - 0x08, 0x30, 0x9f, 0xe5, /* ldr r3,[pc,#8] Get base */ - 0x54, 0x20, 0xa0, 0xe3, /* mov r2,#'T' */ - 0x00, 0x20, 0xc3, 0xe5, /* strb r2,[r3] */ - 0xfb, 0xff, 0xff, 0xea, /* b loop */ - 0x00, 0x10, 0x20, 0x3f, /* 0x3f201000 = UART0 base addr */ + 0x08, 0x30, 0x9f, 0xe5, /* loop: ldr r3, [pc, #8] Get &UART0 */ + 0x54, 0x20, 0xa0, 0xe3, /* mov r2, #'T' */ + 0x00, 0x20, 0xc3, 0xe5, /* strb r2, [r3] *TXDAT = 'T' */ + 0xfb, 0xff, 0xff, 0xea, /* b -12 (loop) */ + 0x00, 0x10, 0x20, 0x3f, /* UART0: 0x3f201000 */ }; static const uint8_t kernel_aarch64[] = { - 0x81, 0x0a, 0x80, 0x52, /* mov w1, #0x54 */ - 0x02, 0x20, 0xa1, 0xd2, /* mov x2, #0x9000000 */ - 0x41, 0x00, 0x00, 0x39, /* strb w1, [x2] */ - 0xfd, 0xff, 0xff, 0x17, /* b -12 (loop) */ + 0x81, 0x0a, 0x80, 0x52, /* loop: mov w1, #'T' */ + 0x02, 0x20, 0xa1, 0xd2, /* mov x2, #0x9000000 Load UART0 */ + 0x41, 0x00, 0x00, 0x39, /* strb w1, [x2] *TXDAT = 'T' */ + 0xfd, 0xff, 0xff, 0x17, /* b -12 (loop) */ }; static const uint8_t kernel_nrf51[] = { From afd757e46166afe86a6df4407b64203e53ea44f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 13 Jan 2025 12:35:33 +0000 Subject: [PATCH 04/11] tests/qtest/boot-serial-test: Reduce for() loop in PL011 tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since registers are not modified, we don't need to refill their values. Directly jump to the previous store instruction to keep filling the TXDAT register. The equivalent C code remains: while (true) { *UART_DATA = 'T'; } Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Fabiano Rosas Signed-off-by: Peter Maydell --- tests/qtest/boot-serial-test.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c index a71d285780..553575ca75 100644 --- a/tests/qtest/boot-serial-test.c +++ b/tests/qtest/boot-serial-test.c @@ -70,18 +70,18 @@ static const uint8_t kernel_plml605[] = { }; static const uint8_t bios_raspi2[] = { - 0x08, 0x30, 0x9f, 0xe5, /* loop: ldr r3, [pc, #8] Get &UART0 */ + 0x08, 0x30, 0x9f, 0xe5, /* ldr r3, [pc, #8] Get &UART0 */ 0x54, 0x20, 0xa0, 0xe3, /* mov r2, #'T' */ - 0x00, 0x20, 0xc3, 0xe5, /* strb r2, [r3] *TXDAT = 'T' */ - 0xfb, 0xff, 0xff, 0xea, /* b -12 (loop) */ + 0x00, 0x20, 0xc3, 0xe5, /* loop: strb r2, [r3] *TXDAT = 'T' */ + 0xff, 0xff, 0xff, 0xea, /* b -4 (loop) */ 0x00, 0x10, 0x20, 0x3f, /* UART0: 0x3f201000 */ }; static const uint8_t kernel_aarch64[] = { - 0x81, 0x0a, 0x80, 0x52, /* loop: mov w1, #'T' */ + 0x81, 0x0a, 0x80, 0x52, /* mov w1, #'T' */ 0x02, 0x20, 0xa1, 0xd2, /* mov x2, #0x9000000 Load UART0 */ - 0x41, 0x00, 0x00, 0x39, /* strb w1, [x2] *TXDAT = 'T' */ - 0xfd, 0xff, 0xff, 0x17, /* b -12 (loop) */ + 0x41, 0x00, 0x00, 0x39, /* loop: strb w1, [x2] *TXDAT = 'T' */ + 0xff, 0xff, 0xff, 0x17, /* b -4 (loop) */ }; static const uint8_t kernel_nrf51[] = { From 80b8b01f89387181378aa251e7a5454470ec5045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 13 Jan 2025 12:35:33 +0000 Subject: [PATCH 05/11] tests/qtest/boot-serial-test: Reorder pair of instructions in PL011 test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the next commit we are going to use a different value for the $w1 register, maintaining the same $x2 value. In order to keep the next commit trivial to review, set $x2 before $w1. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Fabiano Rosas Signed-off-by: Peter Maydell --- tests/qtest/boot-serial-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c index 553575ca75..bcfa504826 100644 --- a/tests/qtest/boot-serial-test.c +++ b/tests/qtest/boot-serial-test.c @@ -78,8 +78,8 @@ static const uint8_t bios_raspi2[] = { }; static const uint8_t kernel_aarch64[] = { - 0x81, 0x0a, 0x80, 0x52, /* mov w1, #'T' */ 0x02, 0x20, 0xa1, 0xd2, /* mov x2, #0x9000000 Load UART0 */ + 0x81, 0x0a, 0x80, 0x52, /* mov w1, #'T' */ 0x41, 0x00, 0x00, 0x39, /* loop: strb w1, [x2] *TXDAT = 'T' */ 0xff, 0xff, 0xff, 0x17, /* b -4 (loop) */ }; From 1bb7f615a517ba85ebdbbd30d8de2120b4598d12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 13 Jan 2025 12:35:33 +0000 Subject: [PATCH 06/11] tests/qtest/boot-serial-test: Initialize PL011 Control register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tests using the PL011 UART of the virt and raspi machines weren't properly enabling the UART and its transmitter previous to sending characters. Follow the PL011 manual initialization recommendation by setting the proper bits of the control register. Update the ASM code prefixing: *UART_CTRL = UART_ENABLE | TX_ENABLE; to: while (true) { *UART_DATA = 'T'; } Note, since commit 51b61dd4d56 ("hw/char/pl011: Warn when using disabled transmitter") incomplete PL011 initialization can be logged using the '-d guest_errors' command line option. Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Peter Maydell --- tests/qtest/boot-serial-test.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c index bcfa504826..ffa9e780ad 100644 --- a/tests/qtest/boot-serial-test.c +++ b/tests/qtest/boot-serial-test.c @@ -70,15 +70,20 @@ static const uint8_t kernel_plml605[] = { }; static const uint8_t bios_raspi2[] = { - 0x08, 0x30, 0x9f, 0xe5, /* ldr r3, [pc, #8] Get &UART0 */ + 0x10, 0x30, 0x9f, 0xe5, /* ldr r3, [pc, #16] Get &UART0 */ + 0x10, 0x20, 0x9f, 0xe5, /* ldr r2, [pc, #16] Get &CR */ + 0xb0, 0x23, 0xc3, 0xe1, /* strh r2, [r3, #48] Set CR */ 0x54, 0x20, 0xa0, 0xe3, /* mov r2, #'T' */ 0x00, 0x20, 0xc3, 0xe5, /* loop: strb r2, [r3] *TXDAT = 'T' */ 0xff, 0xff, 0xff, 0xea, /* b -4 (loop) */ 0x00, 0x10, 0x20, 0x3f, /* UART0: 0x3f201000 */ + 0x01, 0x01, 0x00, 0x00, /* CR: 0x101 = UARTEN|TXE */ }; static const uint8_t kernel_aarch64[] = { 0x02, 0x20, 0xa1, 0xd2, /* mov x2, #0x9000000 Load UART0 */ + 0x21, 0x20, 0x80, 0x52, /* mov w1, 0x101 CR = UARTEN|TXE */ + 0x41, 0x60, 0x00, 0x79, /* strh w1, [x2, #48] Set CR */ 0x81, 0x0a, 0x80, 0x52, /* mov w1, #'T' */ 0x41, 0x00, 0x00, 0x39, /* loop: strb w1, [x2] *TXDAT = 'T' */ 0xff, 0xff, 0xff, 0x17, /* b -4 (loop) */ From 538b764d3417b9295cf7f8b617eb7bc90cbc4ad6 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 13 Jan 2025 12:35:34 +0000 Subject: [PATCH 07/11] target/arm: Move minor arithmetic helpers out of helper.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit helper.c includes some small TCG helper functions used for mostly arithmetic instructions. These are TCG only and there's no need for them to be in the large and unwieldy helper.c. Move them out to their own source file in the tcg/ subdirectory, together with the op_addsub.h multiply-included template header that they use. Since we are moving op_addsub.h, we take the opportunity to give it a name which matches our convention for files which are not true header files but which are #included from other C files: op_addsub.c.inc. (Ironically, this means that helper.c no longer contains any TCG helper function definitions at all.) Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20250110131211.2546314-1-peter.maydell@linaro.org Reviewed-by: Alex Bennée --- target/arm/helper.c | 285 ----------------- target/arm/tcg/arith_helper.c | 296 ++++++++++++++++++ target/arm/tcg/meson.build | 1 + .../arm/{op_addsub.h => tcg/op_addsub.c.inc} | 0 4 files changed, 297 insertions(+), 285 deletions(-) create mode 100644 target/arm/tcg/arith_helper.c rename target/arm/{op_addsub.h => tcg/op_addsub.c.inc} (100%) diff --git a/target/arm/helper.c b/target/arm/helper.c index 5b595f951b..6399767851 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -17,11 +17,9 @@ #include "qemu/main-loop.h" #include "qemu/timer.h" #include "qemu/bitops.h" -#include "qemu/crc32c.h" #include "qemu/qemu-print.h" #include "exec/exec-all.h" #include "exec/translation-block.h" -#include /* for crc32 */ #include "hw/irq.h" #include "system/cpu-timers.h" #include "system/kvm.h" @@ -10984,289 +10982,6 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, }; } -/* - * Note that signed overflow is undefined in C. The following routines are - * careful to use unsigned types where modulo arithmetic is required. - * Failure to do so _will_ break on newer gcc. - */ - -/* Signed saturating arithmetic. */ - -/* Perform 16-bit signed saturating addition. */ -static inline uint16_t add16_sat(uint16_t a, uint16_t b) -{ - uint16_t res; - - res = a + b; - if (((res ^ a) & 0x8000) && !((a ^ b) & 0x8000)) { - if (a & 0x8000) { - res = 0x8000; - } else { - res = 0x7fff; - } - } - return res; -} - -/* Perform 8-bit signed saturating addition. */ -static inline uint8_t add8_sat(uint8_t a, uint8_t b) -{ - uint8_t res; - - res = a + b; - if (((res ^ a) & 0x80) && !((a ^ b) & 0x80)) { - if (a & 0x80) { - res = 0x80; - } else { - res = 0x7f; - } - } - return res; -} - -/* Perform 16-bit signed saturating subtraction. */ -static inline uint16_t sub16_sat(uint16_t a, uint16_t b) -{ - uint16_t res; - - res = a - b; - if (((res ^ a) & 0x8000) && ((a ^ b) & 0x8000)) { - if (a & 0x8000) { - res = 0x8000; - } else { - res = 0x7fff; - } - } - return res; -} - -/* Perform 8-bit signed saturating subtraction. */ -static inline uint8_t sub8_sat(uint8_t a, uint8_t b) -{ - uint8_t res; - - res = a - b; - if (((res ^ a) & 0x80) && ((a ^ b) & 0x80)) { - if (a & 0x80) { - res = 0x80; - } else { - res = 0x7f; - } - } - return res; -} - -#define ADD16(a, b, n) RESULT(add16_sat(a, b), n, 16); -#define SUB16(a, b, n) RESULT(sub16_sat(a, b), n, 16); -#define ADD8(a, b, n) RESULT(add8_sat(a, b), n, 8); -#define SUB8(a, b, n) RESULT(sub8_sat(a, b), n, 8); -#define PFX q - -#include "op_addsub.h" - -/* Unsigned saturating arithmetic. */ -static inline uint16_t add16_usat(uint16_t a, uint16_t b) -{ - uint16_t res; - res = a + b; - if (res < a) { - res = 0xffff; - } - return res; -} - -static inline uint16_t sub16_usat(uint16_t a, uint16_t b) -{ - if (a > b) { - return a - b; - } else { - return 0; - } -} - -static inline uint8_t add8_usat(uint8_t a, uint8_t b) -{ - uint8_t res; - res = a + b; - if (res < a) { - res = 0xff; - } - return res; -} - -static inline uint8_t sub8_usat(uint8_t a, uint8_t b) -{ - if (a > b) { - return a - b; - } else { - return 0; - } -} - -#define ADD16(a, b, n) RESULT(add16_usat(a, b), n, 16); -#define SUB16(a, b, n) RESULT(sub16_usat(a, b), n, 16); -#define ADD8(a, b, n) RESULT(add8_usat(a, b), n, 8); -#define SUB8(a, b, n) RESULT(sub8_usat(a, b), n, 8); -#define PFX uq - -#include "op_addsub.h" - -/* Signed modulo arithmetic. */ -#define SARITH16(a, b, n, op) do { \ - int32_t sum; \ - sum = (int32_t)(int16_t)(a) op (int32_t)(int16_t)(b); \ - RESULT(sum, n, 16); \ - if (sum >= 0) \ - ge |= 3 << (n * 2); \ - } while (0) - -#define SARITH8(a, b, n, op) do { \ - int32_t sum; \ - sum = (int32_t)(int8_t)(a) op (int32_t)(int8_t)(b); \ - RESULT(sum, n, 8); \ - if (sum >= 0) \ - ge |= 1 << n; \ - } while (0) - - -#define ADD16(a, b, n) SARITH16(a, b, n, +) -#define SUB16(a, b, n) SARITH16(a, b, n, -) -#define ADD8(a, b, n) SARITH8(a, b, n, +) -#define SUB8(a, b, n) SARITH8(a, b, n, -) -#define PFX s -#define ARITH_GE - -#include "op_addsub.h" - -/* Unsigned modulo arithmetic. */ -#define ADD16(a, b, n) do { \ - uint32_t sum; \ - sum = (uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b); \ - RESULT(sum, n, 16); \ - if ((sum >> 16) == 1) \ - ge |= 3 << (n * 2); \ - } while (0) - -#define ADD8(a, b, n) do { \ - uint32_t sum; \ - sum = (uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b); \ - RESULT(sum, n, 8); \ - if ((sum >> 8) == 1) \ - ge |= 1 << n; \ - } while (0) - -#define SUB16(a, b, n) do { \ - uint32_t sum; \ - sum = (uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b); \ - RESULT(sum, n, 16); \ - if ((sum >> 16) == 0) \ - ge |= 3 << (n * 2); \ - } while (0) - -#define SUB8(a, b, n) do { \ - uint32_t sum; \ - sum = (uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b); \ - RESULT(sum, n, 8); \ - if ((sum >> 8) == 0) \ - ge |= 1 << n; \ - } while (0) - -#define PFX u -#define ARITH_GE - -#include "op_addsub.h" - -/* Halved signed arithmetic. */ -#define ADD16(a, b, n) \ - RESULT(((int32_t)(int16_t)(a) + (int32_t)(int16_t)(b)) >> 1, n, 16) -#define SUB16(a, b, n) \ - RESULT(((int32_t)(int16_t)(a) - (int32_t)(int16_t)(b)) >> 1, n, 16) -#define ADD8(a, b, n) \ - RESULT(((int32_t)(int8_t)(a) + (int32_t)(int8_t)(b)) >> 1, n, 8) -#define SUB8(a, b, n) \ - RESULT(((int32_t)(int8_t)(a) - (int32_t)(int8_t)(b)) >> 1, n, 8) -#define PFX sh - -#include "op_addsub.h" - -/* Halved unsigned arithmetic. */ -#define ADD16(a, b, n) \ - RESULT(((uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b)) >> 1, n, 16) -#define SUB16(a, b, n) \ - RESULT(((uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b)) >> 1, n, 16) -#define ADD8(a, b, n) \ - RESULT(((uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b)) >> 1, n, 8) -#define SUB8(a, b, n) \ - RESULT(((uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b)) >> 1, n, 8) -#define PFX uh - -#include "op_addsub.h" - -static inline uint8_t do_usad(uint8_t a, uint8_t b) -{ - if (a > b) { - return a - b; - } else { - return b - a; - } -} - -/* Unsigned sum of absolute byte differences. */ -uint32_t HELPER(usad8)(uint32_t a, uint32_t b) -{ - uint32_t sum; - sum = do_usad(a, b); - sum += do_usad(a >> 8, b >> 8); - sum += do_usad(a >> 16, b >> 16); - sum += do_usad(a >> 24, b >> 24); - return sum; -} - -/* For ARMv6 SEL instruction. */ -uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b) -{ - uint32_t mask; - - mask = 0; - if (flags & 1) { - mask |= 0xff; - } - if (flags & 2) { - mask |= 0xff00; - } - if (flags & 4) { - mask |= 0xff0000; - } - if (flags & 8) { - mask |= 0xff000000; - } - return (a & mask) | (b & ~mask); -} - -/* - * CRC helpers. - * The upper bytes of val (above the number specified by 'bytes') must have - * been zeroed out by the caller. - */ -uint32_t HELPER(crc32)(uint32_t acc, uint32_t val, uint32_t bytes) -{ - uint8_t buf[4]; - - stl_le_p(buf, val); - - /* zlib crc32 converts the accumulator and output to one's complement. */ - return crc32(acc ^ 0xffffffff, buf, bytes) ^ 0xffffffff; -} - -uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes) -{ - uint8_t buf[4]; - - stl_le_p(buf, val); - - /* Linux crc32c converts the output to one's complement. */ - return crc32c(acc, buf, bytes) ^ 0xffffffff; -} /* * Return the exception level to which FP-disabled exceptions should diff --git a/target/arm/tcg/arith_helper.c b/target/arm/tcg/arith_helper.c new file mode 100644 index 0000000000..9a555c7966 --- /dev/null +++ b/target/arm/tcg/arith_helper.c @@ -0,0 +1,296 @@ +/* + * ARM generic helpers for various arithmetical operations. + * + * This code is licensed under the GNU GPL v2 or later. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/helper-proto.h" +#include "qemu/crc32c.h" +#include /* for crc32 */ + +/* + * Note that signed overflow is undefined in C. The following routines are + * careful to use unsigned types where modulo arithmetic is required. + * Failure to do so _will_ break on newer gcc. + */ + +/* Signed saturating arithmetic. */ + +/* Perform 16-bit signed saturating addition. */ +static inline uint16_t add16_sat(uint16_t a, uint16_t b) +{ + uint16_t res; + + res = a + b; + if (((res ^ a) & 0x8000) && !((a ^ b) & 0x8000)) { + if (a & 0x8000) { + res = 0x8000; + } else { + res = 0x7fff; + } + } + return res; +} + +/* Perform 8-bit signed saturating addition. */ +static inline uint8_t add8_sat(uint8_t a, uint8_t b) +{ + uint8_t res; + + res = a + b; + if (((res ^ a) & 0x80) && !((a ^ b) & 0x80)) { + if (a & 0x80) { + res = 0x80; + } else { + res = 0x7f; + } + } + return res; +} + +/* Perform 16-bit signed saturating subtraction. */ +static inline uint16_t sub16_sat(uint16_t a, uint16_t b) +{ + uint16_t res; + + res = a - b; + if (((res ^ a) & 0x8000) && ((a ^ b) & 0x8000)) { + if (a & 0x8000) { + res = 0x8000; + } else { + res = 0x7fff; + } + } + return res; +} + +/* Perform 8-bit signed saturating subtraction. */ +static inline uint8_t sub8_sat(uint8_t a, uint8_t b) +{ + uint8_t res; + + res = a - b; + if (((res ^ a) & 0x80) && ((a ^ b) & 0x80)) { + if (a & 0x80) { + res = 0x80; + } else { + res = 0x7f; + } + } + return res; +} + +#define ADD16(a, b, n) RESULT(add16_sat(a, b), n, 16); +#define SUB16(a, b, n) RESULT(sub16_sat(a, b), n, 16); +#define ADD8(a, b, n) RESULT(add8_sat(a, b), n, 8); +#define SUB8(a, b, n) RESULT(sub8_sat(a, b), n, 8); +#define PFX q + +#include "op_addsub.c.inc" + +/* Unsigned saturating arithmetic. */ +static inline uint16_t add16_usat(uint16_t a, uint16_t b) +{ + uint16_t res; + res = a + b; + if (res < a) { + res = 0xffff; + } + return res; +} + +static inline uint16_t sub16_usat(uint16_t a, uint16_t b) +{ + if (a > b) { + return a - b; + } else { + return 0; + } +} + +static inline uint8_t add8_usat(uint8_t a, uint8_t b) +{ + uint8_t res; + res = a + b; + if (res < a) { + res = 0xff; + } + return res; +} + +static inline uint8_t sub8_usat(uint8_t a, uint8_t b) +{ + if (a > b) { + return a - b; + } else { + return 0; + } +} + +#define ADD16(a, b, n) RESULT(add16_usat(a, b), n, 16); +#define SUB16(a, b, n) RESULT(sub16_usat(a, b), n, 16); +#define ADD8(a, b, n) RESULT(add8_usat(a, b), n, 8); +#define SUB8(a, b, n) RESULT(sub8_usat(a, b), n, 8); +#define PFX uq + +#include "op_addsub.c.inc" + +/* Signed modulo arithmetic. */ +#define SARITH16(a, b, n, op) do { \ + int32_t sum; \ + sum = (int32_t)(int16_t)(a) op (int32_t)(int16_t)(b); \ + RESULT(sum, n, 16); \ + if (sum >= 0) \ + ge |= 3 << (n * 2); \ + } while (0) + +#define SARITH8(a, b, n, op) do { \ + int32_t sum; \ + sum = (int32_t)(int8_t)(a) op (int32_t)(int8_t)(b); \ + RESULT(sum, n, 8); \ + if (sum >= 0) \ + ge |= 1 << n; \ + } while (0) + + +#define ADD16(a, b, n) SARITH16(a, b, n, +) +#define SUB16(a, b, n) SARITH16(a, b, n, -) +#define ADD8(a, b, n) SARITH8(a, b, n, +) +#define SUB8(a, b, n) SARITH8(a, b, n, -) +#define PFX s +#define ARITH_GE + +#include "op_addsub.c.inc" + +/* Unsigned modulo arithmetic. */ +#define ADD16(a, b, n) do { \ + uint32_t sum; \ + sum = (uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b); \ + RESULT(sum, n, 16); \ + if ((sum >> 16) == 1) \ + ge |= 3 << (n * 2); \ + } while (0) + +#define ADD8(a, b, n) do { \ + uint32_t sum; \ + sum = (uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b); \ + RESULT(sum, n, 8); \ + if ((sum >> 8) == 1) \ + ge |= 1 << n; \ + } while (0) + +#define SUB16(a, b, n) do { \ + uint32_t sum; \ + sum = (uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b); \ + RESULT(sum, n, 16); \ + if ((sum >> 16) == 0) \ + ge |= 3 << (n * 2); \ + } while (0) + +#define SUB8(a, b, n) do { \ + uint32_t sum; \ + sum = (uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b); \ + RESULT(sum, n, 8); \ + if ((sum >> 8) == 0) \ + ge |= 1 << n; \ + } while (0) + +#define PFX u +#define ARITH_GE + +#include "op_addsub.c.inc" + +/* Halved signed arithmetic. */ +#define ADD16(a, b, n) \ + RESULT(((int32_t)(int16_t)(a) + (int32_t)(int16_t)(b)) >> 1, n, 16) +#define SUB16(a, b, n) \ + RESULT(((int32_t)(int16_t)(a) - (int32_t)(int16_t)(b)) >> 1, n, 16) +#define ADD8(a, b, n) \ + RESULT(((int32_t)(int8_t)(a) + (int32_t)(int8_t)(b)) >> 1, n, 8) +#define SUB8(a, b, n) \ + RESULT(((int32_t)(int8_t)(a) - (int32_t)(int8_t)(b)) >> 1, n, 8) +#define PFX sh + +#include "op_addsub.c.inc" + +/* Halved unsigned arithmetic. */ +#define ADD16(a, b, n) \ + RESULT(((uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b)) >> 1, n, 16) +#define SUB16(a, b, n) \ + RESULT(((uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b)) >> 1, n, 16) +#define ADD8(a, b, n) \ + RESULT(((uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b)) >> 1, n, 8) +#define SUB8(a, b, n) \ + RESULT(((uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b)) >> 1, n, 8) +#define PFX uh + +#include "op_addsub.c.inc" + +static inline uint8_t do_usad(uint8_t a, uint8_t b) +{ + if (a > b) { + return a - b; + } else { + return b - a; + } +} + +/* Unsigned sum of absolute byte differences. */ +uint32_t HELPER(usad8)(uint32_t a, uint32_t b) +{ + uint32_t sum; + sum = do_usad(a, b); + sum += do_usad(a >> 8, b >> 8); + sum += do_usad(a >> 16, b >> 16); + sum += do_usad(a >> 24, b >> 24); + return sum; +} + +/* For ARMv6 SEL instruction. */ +uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b) +{ + uint32_t mask; + + mask = 0; + if (flags & 1) { + mask |= 0xff; + } + if (flags & 2) { + mask |= 0xff00; + } + if (flags & 4) { + mask |= 0xff0000; + } + if (flags & 8) { + mask |= 0xff000000; + } + return (a & mask) | (b & ~mask); +} + +/* + * CRC helpers. + * The upper bytes of val (above the number specified by 'bytes') must have + * been zeroed out by the caller. + */ +uint32_t HELPER(crc32)(uint32_t acc, uint32_t val, uint32_t bytes) +{ + uint8_t buf[4]; + + stl_le_p(buf, val); + + /* zlib crc32 converts the accumulator and output to one's complement. */ + return crc32(acc ^ 0xffffffff, buf, bytes) ^ 0xffffffff; +} + +uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes) +{ + uint8_t buf[4]; + + stl_le_p(buf, val); + + /* Linux crc32c converts the output to one's complement. */ + return crc32c(acc, buf, bytes) ^ 0xffffffff; +} diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build index 09238989c5..1f9077c372 100644 --- a/target/arm/tcg/meson.build +++ b/target/arm/tcg/meson.build @@ -40,6 +40,7 @@ arm_ss.add(files( 'tlb_helper.c', 'vec_helper.c', 'tlb-insns.c', + 'arith_helper.c', )) arm_ss.add(when: 'TARGET_AARCH64', if_true: files( diff --git a/target/arm/op_addsub.h b/target/arm/tcg/op_addsub.c.inc similarity index 100% rename from target/arm/op_addsub.h rename to target/arm/tcg/op_addsub.c.inc From 86a00f2046f5f5b613bdf18d6c972b495a907c37 Mon Sep 17 00:00:00 2001 From: Pierrick Bouvier Date: Mon, 13 Jan 2025 12:35:34 +0000 Subject: [PATCH 08/11] target/arm: add new property to select pauth-qarma5 Before changing default pauth algorithm, we need to make sure current default one (QARMA5) can still be selected. $ qemu-system-aarch64 -cpu max,pauth-qarma5=on ... Signed-off-by: Pierrick Bouvier Reviewed-by: Richard Henderson Message-id: 20241219183211.3493974-2-pierrick.bouvier@linaro.org Signed-off-by: Peter Maydell --- docs/system/arm/cpu-features.rst | 5 ++++- target/arm/arm-qmp-cmds.c | 2 +- target/arm/cpu.h | 1 + target/arm/cpu64.c | 20 ++++++++++++++------ tests/qtest/arm-cpu-features.c | 15 +++++++++++---- 5 files changed, 31 insertions(+), 12 deletions(-) diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst index a5fb929243..d69ebc2b85 100644 --- a/docs/system/arm/cpu-features.rst +++ b/docs/system/arm/cpu-features.rst @@ -219,7 +219,10 @@ Below is the list of TCG VCPU features and their descriptions. ``pauth-qarma3`` When ``pauth`` is enabled, select the architected QARMA3 algorithm. -Without either ``pauth-impdef`` or ``pauth-qarma3`` enabled, +``pauth-qarma5`` + When ``pauth`` is enabled, select the architected QARMA5 algorithm. + +Without ``pauth-impdef``, ``pauth-qarma3`` or ``pauth-qarma5`` enabled, the architected QARMA5 algorithm is used. The architected QARMA5 and QARMA3 algorithms have good cryptographic properties, but can be quite slow to emulate. The impdef algorithm used by QEMU is diff --git a/target/arm/arm-qmp-cmds.c b/target/arm/arm-qmp-cmds.c index 3cc8cc738b..33cea080d1 100644 --- a/target/arm/arm-qmp-cmds.c +++ b/target/arm/arm-qmp-cmds.c @@ -94,7 +94,7 @@ static const char *cpu_model_advertised_features[] = { "sve640", "sve768", "sve896", "sve1024", "sve1152", "sve1280", "sve1408", "sve1536", "sve1664", "sve1792", "sve1920", "sve2048", "kvm-no-adjvtime", "kvm-steal-time", - "pauth", "pauth-impdef", "pauth-qarma3", + "pauth", "pauth-impdef", "pauth-qarma3", "pauth-qarma5", NULL }; diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 12b8466542..01d9ff1781 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1062,6 +1062,7 @@ struct ArchCPU { bool prop_pauth; bool prop_pauth_impdef; bool prop_pauth_qarma3; + bool prop_pauth_qarma5; bool prop_lpa2; /* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */ diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index dca83e4518..6ee0af6912 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -520,9 +520,12 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) } if (cpu->prop_pauth) { - if (cpu->prop_pauth_impdef && cpu->prop_pauth_qarma3) { + if ((cpu->prop_pauth_impdef && cpu->prop_pauth_qarma3) || + (cpu->prop_pauth_impdef && cpu->prop_pauth_qarma5) || + (cpu->prop_pauth_qarma3 && cpu->prop_pauth_qarma5)) { error_setg(errp, - "cannot enable both pauth-impdef and pauth-qarma3"); + "cannot enable pauth-impdef, pauth-qarma3 and " + "pauth-qarma5 at the same time"); return; } @@ -532,13 +535,15 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) } else if (cpu->prop_pauth_qarma3) { isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, APA3, features); isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, GPA3, 1); - } else { + } else { /* default is pauth-qarma5 */ isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, APA, features); isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPA, 1); } - } else if (cpu->prop_pauth_impdef || cpu->prop_pauth_qarma3) { - error_setg(errp, "cannot enable pauth-impdef or " - "pauth-qarma3 without pauth"); + } else if (cpu->prop_pauth_impdef || + cpu->prop_pauth_qarma3 || + cpu->prop_pauth_qarma5) { + error_setg(errp, "cannot enable pauth-impdef, pauth-qarma3 or " + "pauth-qarma5 without pauth"); error_append_hint(errp, "Add pauth=on to the CPU property list.\n"); } } @@ -553,6 +558,8 @@ static const Property arm_cpu_pauth_impdef_property = DEFINE_PROP_BOOL("pauth-impdef", ARMCPU, prop_pauth_impdef, false); static const Property arm_cpu_pauth_qarma3_property = DEFINE_PROP_BOOL("pauth-qarma3", ARMCPU, prop_pauth_qarma3, false); +static Property arm_cpu_pauth_qarma5_property = + DEFINE_PROP_BOOL("pauth-qarma5", ARMCPU, prop_pauth_qarma5, false); void aarch64_add_pauth_properties(Object *obj) { @@ -573,6 +580,7 @@ void aarch64_add_pauth_properties(Object *obj) } else { qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_impdef_property); qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_qarma3_property); + qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_qarma5_property); } } diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c index cfd6f77353..98d6c970ea 100644 --- a/tests/qtest/arm-cpu-features.c +++ b/tests/qtest/arm-cpu-features.c @@ -419,21 +419,28 @@ static void pauth_tests_default(QTestState *qts, const char *cpu_type) assert_has_feature_enabled(qts, cpu_type, "pauth"); assert_has_feature_disabled(qts, cpu_type, "pauth-impdef"); assert_has_feature_disabled(qts, cpu_type, "pauth-qarma3"); + assert_has_feature_disabled(qts, cpu_type, "pauth-qarma5"); assert_set_feature(qts, cpu_type, "pauth", false); assert_set_feature(qts, cpu_type, "pauth", true); assert_set_feature(qts, cpu_type, "pauth-impdef", true); assert_set_feature(qts, cpu_type, "pauth-impdef", false); assert_set_feature(qts, cpu_type, "pauth-qarma3", true); assert_set_feature(qts, cpu_type, "pauth-qarma3", false); + assert_set_feature(qts, cpu_type, "pauth-qarma5", true); + assert_set_feature(qts, cpu_type, "pauth-qarma5", false); assert_error(qts, cpu_type, - "cannot enable pauth-impdef or pauth-qarma3 without pauth", + "cannot enable pauth-impdef, pauth-qarma3 or pauth-qarma5 without pauth", "{ 'pauth': false, 'pauth-impdef': true }"); assert_error(qts, cpu_type, - "cannot enable pauth-impdef or pauth-qarma3 without pauth", + "cannot enable pauth-impdef, pauth-qarma3 or pauth-qarma5 without pauth", "{ 'pauth': false, 'pauth-qarma3': true }"); assert_error(qts, cpu_type, - "cannot enable both pauth-impdef and pauth-qarma3", - "{ 'pauth': true, 'pauth-impdef': true, 'pauth-qarma3': true }"); + "cannot enable pauth-impdef, pauth-qarma3 or pauth-qarma5 without pauth", + "{ 'pauth': false, 'pauth-qarma5': true }"); + assert_error(qts, cpu_type, + "cannot enable pauth-impdef, pauth-qarma3 and pauth-qarma5 at the same time", + "{ 'pauth': true, 'pauth-impdef': true, 'pauth-qarma3': true," + " 'pauth-qarma5': true }"); } static void test_query_cpu_model_expansion(const void *data) From 39d70016d9abe15967f7051741dd5621c659b1f4 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 13 Jan 2025 12:35:34 +0000 Subject: [PATCH 09/11] tests/tcg/aarch64: force qarma5 for pauth-3 test The pauth-3 test explicitly tests that a computation of the pointer-authentication produces the expected result. This means that it must be run with the QARMA5 algorithm. Explicitly set the pauth algorithm when running this test, so that it doesn't break when we change the default algorithm the 'max' CPU uses. Signed-off-by: Peter Maydell --- tests/tcg/aarch64/Makefile.softmmu-target | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target index d08d9b01de..9c52475b7a 100644 --- a/tests/tcg/aarch64/Makefile.softmmu-target +++ b/tests/tcg/aarch64/Makefile.softmmu-target @@ -91,6 +91,9 @@ EXTRA_RUNS+=run-memory-replay ifneq ($(CROSS_CC_HAS_ARMV8_3),) pauth-3: CFLAGS += $(CROSS_CC_HAS_ARMV8_3) +# This test explicitly checks the output of the pauth operation so we +# must force the use of the QARMA5 algorithm for it. +run-pauth-3: QEMU_BASE_MACHINE=-M virt -cpu max,pauth-qarma5=on -display none else pauth-3: $(call skip-test, "BUILD of $@", "missing compiler support") From 132f8ec799cea261ad6b60ac8ae86f17cc98b9a1 Mon Sep 17 00:00:00 2001 From: Pierrick Bouvier Date: Mon, 13 Jan 2025 12:35:34 +0000 Subject: [PATCH 10/11] target/arm: change default pauth algorithm to impdef Pointer authentication on aarch64 is pretty expensive (up to 50% of execution time) when running a virtual machine with tcg and -cpu max (which enables pauth=on). The advice is always: use pauth-impdef=on. Our documentation even mentions it "by default" in docs/system/introduction.rst. Thus, we change the default to use impdef by default. This does not affect kvm or hvf acceleration, since pauth algorithm used is the one from host cpu. This change is retro compatible, in terms of cli, with previous versions, as the semantic of using -cpu max,pauth-impdef=on, and -cpu max,pauth-qarma3=on is preserved. The new option introduced in previous patch and matching old default is -cpu max,pauth-qarma5=on. It is retro compatible with migration as well, by defining a backcompat property, that will use qarma5 by default for virt machine <= 9.2. Tested by saving and restoring a vm from qemu 9.2.0 into qemu-master (10.0) for cpus neoverse-n2 and max. Signed-off-by: Pierrick Bouvier Reviewed-by: Richard Henderson Message-id: 20241219183211.3493974-3-pierrick.bouvier@linaro.org Signed-off-by: Peter Maydell --- docs/system/arm/cpu-features.rst | 2 +- docs/system/introduction.rst | 2 +- hw/core/machine.c | 4 +++- target/arm/cpu.c | 2 ++ target/arm/cpu.h | 3 +++ target/arm/cpu64.c | 22 ++++++++++++++++------ 6 files changed, 26 insertions(+), 9 deletions(-) diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst index d69ebc2b85..37d5dfd15b 100644 --- a/docs/system/arm/cpu-features.rst +++ b/docs/system/arm/cpu-features.rst @@ -223,7 +223,7 @@ Below is the list of TCG VCPU features and their descriptions. When ``pauth`` is enabled, select the architected QARMA5 algorithm. Without ``pauth-impdef``, ``pauth-qarma3`` or ``pauth-qarma5`` enabled, -the architected QARMA5 algorithm is used. The architected QARMA5 +the QEMU impdef algorithm is used. The architected QARMA5 and QARMA3 algorithms have good cryptographic properties, but can be quite slow to emulate. The impdef algorithm used by QEMU is non-cryptographic but significantly faster. diff --git a/docs/system/introduction.rst b/docs/system/introduction.rst index 746707eb00..338d3745c3 100644 --- a/docs/system/introduction.rst +++ b/docs/system/introduction.rst @@ -169,7 +169,7 @@ would default to it anyway. .. code:: - -cpu max,pauth-impdef=on \ + -cpu max \ -smp 4 \ -accel tcg \ diff --git a/hw/core/machine.c b/hw/core/machine.c index c949af9766..c23b399496 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -36,7 +36,9 @@ #include "hw/virtio/virtio-iommu.h" #include "audio/audio.h" -GlobalProperty hw_compat_9_2[] = {}; +GlobalProperty hw_compat_9_2[] = { + {"arm-cpu", "backcompat-pauth-default-use-qarma5", "true"}, +}; const size_t hw_compat_9_2_len = G_N_ELEMENTS(hw_compat_9_2); GlobalProperty hw_compat_9_1[] = { diff --git a/target/arm/cpu.c b/target/arm/cpu.c index dcedadc89e..dc0231233a 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -2653,6 +2653,8 @@ static const Property arm_cpu_properties[] = { DEFINE_PROP_INT32("core-count", ARMCPU, core_count, -1), /* True to default to the backward-compat old CNTFRQ rather than 1Ghz */ DEFINE_PROP_BOOL("backcompat-cntfrq", ARMCPU, backcompat_cntfrq, false), + DEFINE_PROP_BOOL("backcompat-pauth-default-use-qarma5", ARMCPU, + backcompat_pauth_default_use_qarma5, false), }; static const gchar *arm_gdb_arch_name(CPUState *cs) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 01d9ff1781..9a6e8e589c 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -972,6 +972,9 @@ struct ArchCPU { /* QOM property to indicate we should use the back-compat CNTFRQ default */ bool backcompat_cntfrq; + /* QOM property to indicate we should use the back-compat QARMA5 default */ + bool backcompat_pauth_default_use_qarma5; + /* Specify the number of cores in this CPU cluster. Used for the L2CTLR * register. */ diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 6ee0af6912..8188ede5cc 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -529,15 +529,25 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) return; } - if (cpu->prop_pauth_impdef) { - isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, API, features); - isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPI, 1); + bool use_default = !cpu->prop_pauth_qarma5 && + !cpu->prop_pauth_qarma3 && + !cpu->prop_pauth_impdef; + + if (cpu->prop_pauth_qarma5 || + (use_default && + cpu->backcompat_pauth_default_use_qarma5)) { + isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, APA, features); + isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPA, 1); } else if (cpu->prop_pauth_qarma3) { isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, APA3, features); isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, GPA3, 1); - } else { /* default is pauth-qarma5 */ - isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, APA, features); - isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPA, 1); + } else if (cpu->prop_pauth_impdef || + (use_default && + !cpu->backcompat_pauth_default_use_qarma5)) { + isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, API, features); + isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPI, 1); + } else { + g_assert_not_reached(); } } else if (cpu->prop_pauth_impdef || cpu->prop_pauth_qarma3 || From 435d260e7ec5ff9c79e3e62f1d66ec82d2d691ae Mon Sep 17 00:00:00 2001 From: Pierrick Bouvier Date: Mon, 13 Jan 2025 12:35:35 +0000 Subject: [PATCH 11/11] docs/system/arm/virt: mention specific migration information Signed-off-by: Pierrick Bouvier Message-id: 20241219183211.3493974-4-pierrick.bouvier@linaro.org [PMM: Removed a paragraph about using non-versioned models.] Signed-off-by: Peter Maydell --- docs/system/arm/virt.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst index f87adeb444..766a7455f0 100644 --- a/docs/system/arm/virt.rst +++ b/docs/system/arm/virt.rst @@ -19,6 +19,10 @@ of the 5.0 release and ``virt-5.0`` of the 5.1 release. Migration is not guaranteed to work between different QEMU releases for the non-versioned ``virt`` machine type. +VM migration is not guaranteed when using ``-cpu max``, as features +supported may change between QEMU versions. To ensure your VM can be +migrated, it is recommended to use another cpu model instead. + Supported devices """""""""""""""""