git: 167d3567c4b9 - main - arm64/vmm: Treat Rt=31 as xzr in reg & instr emul
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 13 Oct 2026 15:44:57 UTC
The branch main has been updated by andrew:
URL: https://cgit.FreeBSD.org/src/commit/?id=167d3567c4b93650c8bcca86ff294226e6e1a9ce
commit 167d3567c4b93650c8bcca86ff294226e6e1a9ce
Author: Kajetan Puchalski <kajetan.puchalski@arm.com>
AuthorDate: 2026-09-29 17:02:19 +0000
Commit: Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2026-10-13 15:44:34 +0000
arm64/vmm: Treat Rt=31 as xzr in reg & instr emul
For certain instructions like msr, mrs, ldr & str, Rt=31 means the
operand is the Zero register (XZR) as opposed to the SP, even though the
two share the encoding of 31 on AArch64.
This is currently ignored in register and instruction emulation, so
emulated guest operations like "msr <reg>, xzr" will set the value of
<reg> to the current value of the SP instead of to 0.
Skip set and get operations when Rt=31 to correct the behaviour.
Signed-off-by: Kajetan Puchalski <kajetan.puchalski@arm.com>
Reviewed by: andrew
Sponsored by: Arm Ltd
Pull Request: https://github.com/freebsd/freebsd-src/pull/2454
---
sys/arm64/vmm/vmm_instruction_emul.c | 33 +++++++++++++++++++++++++--------
1 file changed, 25 insertions(+), 8 deletions(-)
diff --git a/sys/arm64/vmm/vmm_instruction_emul.c b/sys/arm64/vmm/vmm_instruction_emul.c
index 3d3326d6eda5..484539e9cc52 100644
--- a/sys/arm64/vmm/vmm_instruction_emul.c
+++ b/sys/arm64/vmm/vmm_instruction_emul.c
@@ -63,11 +63,16 @@ vmm_emulate_instruction(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
error = memread(vcpu, gpa, &val, vie->access_size, memarg);
if (error)
goto out;
- error = vm_set_register(vcpu, vie->reg, val);
+ /* Make sure we treat Rt=31 as xzr and not SP */
+ if (vie->reg != 31)
+ error = vm_set_register(vcpu, vie->reg, val);
} else {
- error = vm_get_register(vcpu, vie->reg, &val);
- if (error)
- goto out;
+ val = 0;
+ if (vie->reg != 31) {
+ error = vm_get_register(vcpu, vie->reg, &val);
+ if (error)
+ goto out;
+ }
/* Mask any unneeded bits from the register */
if (vie->access_size < 8)
val &= (1ul << (vie->access_size * 8)) - 1;
@@ -89,11 +94,23 @@ vmm_emulate_register(struct vcpu *vcpu, struct vre *vre, reg_read_t regread,
error = regread(vcpu, &val, regarg);
if (error)
goto out;
- error = vm_set_register(vcpu, vre->reg, val);
+ /*
+ * vre->reg here comes from msr/mrs Rt, where 31 means "xzr" as
+ * opposed to "SP". Reading into xzr must not set the register.
+ */
+ if (vre->reg != 31)
+ error = vm_set_register(vcpu, vre->reg, val);
} else {
- error = vm_get_register(vcpu, vre->reg, &val);
- if (error)
- goto out;
+ val = 0;
+ /*
+ * Writing xzr into a register must write 0, instead of the
+ * value of SP.
+ */
+ if (vre->reg != 31) {
+ error = vm_get_register(vcpu, vre->reg, &val);
+ if (error)
+ goto out;
+ }
error = regwrite(vcpu, val, regarg);
}