arch/x86/include/asm/vmware.h | 72 +++++++++++++++++------------------ 1 file changed, 34 insertions(+), 38 deletions(-)
Fedora QA reported the following panic:
BUG: unable to handle page fault for address: 0000000040003e54
#PF: supervisor write access in kernel mode
#PF: error_code(0x0002) - not-present page
PGD 1082ec067 P4D 0
Oops: Oops: 0002 [#1] SMP NOPTI
CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 6.19.0-0.rc4.260108gf0b9d8eb98df.34.fc43.x86_64 #1 PREEMPT(lazy)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS edk2-20251119-3.fc43 11/19/2025
RIP: 0010:vmware_hypercall4.constprop.0+0x52/0x90
Code: 48 83 c4 20 5b e9 69 f0 fc fe 8b 05 a0 c1 b2 01 85 c0 74 23 b8 68 58 4d 56 b9 27 00 00 00 31 d2 bb 04 00 00 00 66 ba 58 56 ed <89> 1f 89 0e 41 89 10 5b e9 3c f0 fc fe 6a 00 49 89 f9 45 31 c0 31
RSP: 0018:ff5eeb3240003e40 EFLAGS: 00010046
RAX: 0000000000000000 RBX: 000000000000ffca RCX: 000000000000ffac
RDX: 0000000000000000 RSI: 0000000040003e58 RDI: 0000000040003e54
RBP: ff1e05f3c1204800 R08: ff5eeb3240003e5c R09: 000000009d899c41
R10: 000000000000003d R11: ff5eeb3240003ff8 R12: 0000000000000000
R13: 00000000000000ff R14: ff1e05f3c02f9e00 R15: 000000000000000c
FS: 0000000000000000(0000) GS:ff1e05f489e40000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000040003e54 CR3: 000000010841d002 CR4: 0000000000771ef0
PKRU: 55555554
Call Trace:
<IRQ>
vmmouse_report_events+0x13e/0x1b0
psmouse_handle_byte+0x15/0x60
ps2_interrupt+0x8a/0xd0
...
The panic was triggered by dereferencing a bad pointer (in RDI)
immediately after a VMware hypercall:
ffffffff82135070 <vmware_hypercall4.constprop.0>:
...
ffffffff821350ac: b8 68 58 4d 56 mov $0x564d5868,%eax
ffffffff821350b1: b9 27 00 00 00 mov $0x27,%ecx
ffffffff821350b6: 31 d2 xor %edx,%edx
ffffffff821350b8: bb 04 00 00 00 mov $0x4,%ebx
ffffffff821350bd: 66 ba 58 56 mov $0x5658,%dx
ffffffff821350c1: ed in (%dx),%eax <-- hypercall
ffffffff821350c2: 89 1f mov %ebx,(%rdi) <-- crash
Reading the disassembly shows that RDI should contain the value of a
valid kernel stack address here (0xff5eeb3240003e54). Instead it
contains 0x40003e54, suggesting the hypervisor cleared the upper 32
bits.
This issue was bisected to commit aca282ab7e75 ("x86/asm: Annotate
special section entries"), which added annotations to the ALTERNATIVE()
macro. Despite the use of asm_inline, that commit caused the compiler
to un-inline and const-propagate vmware_hypercall4().
That made RDI live across the hypercall, making the hypervisor's
register clobbering visible and exposing this latent bug.
The open-vm-tools reference implementation treats all six registers as
clobbered for all hypercalls. Match that behavior here.
Fixes: 34bf25e820ae ("x86/vmware: Introduce VMware hypercall API")
Fixes: aca282ab7e75 ("x86/asm: Annotate special section entries")
Reported-by: Justin Forbes <jforbes@fedoraproject.org>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
arch/x86/include/asm/vmware.h | 72 +++++++++++++++++------------------
1 file changed, 34 insertions(+), 38 deletions(-)
diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h
index c9cf43d5ef23..372173d4ea27 100644
--- a/arch/x86/include/asm/vmware.h
+++ b/arch/x86/include/asm/vmware.h
@@ -98,7 +98,7 @@ extern unsigned long vmware_tdx_hypercall(unsigned long cmd,
static inline
unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1)
{
- unsigned long out0;
+ unsigned long out0, tmp = 0;
if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
@@ -109,13 +109,11 @@ unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1)
NULL, NULL, NULL, NULL, NULL);
asm_inline volatile (VMWARE_HYPERCALL
- : "=a" (out0)
+ : "=a" (out0), "+b" (in1), "+c" (cmd), "+d" (tmp)
: [port] "i" (VMWARE_HYPERVISOR_PORT),
- "a" (VMWARE_HYPERVISOR_MAGIC),
- "b" (in1),
- "c" (cmd),
- "d" (0)
- : "cc", "memory");
+ "a" (VMWARE_HYPERVISOR_MAGIC)
+ : "di", "si", "cc", "memory");
+
return out0;
}
@@ -123,7 +121,7 @@ static inline
unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1,
u32 *out1, u32 *out2)
{
- unsigned long out0;
+ unsigned long out0, tmp = 0;
if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
@@ -134,13 +132,13 @@ unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1,
out1, out2, NULL, NULL, NULL);
asm_inline volatile (VMWARE_HYPERCALL
- : "=a" (out0), "=b" (*out1), "=c" (*out2)
+ : "=a" (out0), "=b" (*out1), "=c" (*out2), "+d" (tmp)
: [port] "i" (VMWARE_HYPERVISOR_PORT),
"a" (VMWARE_HYPERVISOR_MAGIC),
"b" (in1),
- "c" (cmd),
- "d" (0)
- : "cc", "memory");
+ "c" (cmd)
+ : "di", "si", "cc", "memory");
+
return out0;
}
@@ -165,7 +163,8 @@ unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1,
"b" (in1),
"c" (cmd),
"d" (0)
- : "cc", "memory");
+ : "di", "si", "cc", "memory");
+
return out0;
}
@@ -185,15 +184,13 @@ unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1,
NULL, out2, NULL, NULL, NULL);
asm_inline volatile (VMWARE_HYPERCALL
- : "=a" (out0), "=c" (*out2)
+ : "=a" (out0), "+b" (in1), "=c" (*out2), "+d" (in3),
+ "+S" (in4), "+D" (in5)
: [port] "i" (VMWARE_HYPERVISOR_PORT),
"a" (VMWARE_HYPERVISOR_MAGIC),
- "b" (in1),
- "c" (cmd),
- "d" (in3),
- "S" (in4),
- "D" (in5)
+ "c" (cmd)
: "cc", "memory");
+
return out0;
}
@@ -213,14 +210,14 @@ unsigned long vmware_hypercall6(unsigned long cmd, unsigned long in1,
NULL, out2, out3, out4, out5);
asm_inline volatile (VMWARE_HYPERCALL
- : "=a" (out0), "=c" (*out2), "=d" (*out3), "=S" (*out4),
- "=D" (*out5)
+ : "=a" (out0), "+b" (in1), "=c" (*out2), "=d" (*out3),
+ "=S" (*out4), "=D" (*out5)
: [port] "i" (VMWARE_HYPERVISOR_PORT),
"a" (VMWARE_HYPERVISOR_MAGIC),
- "b" (in1),
"c" (cmd),
"d" (in3)
: "cc", "memory");
+
return out0;
}
@@ -241,15 +238,15 @@ unsigned long vmware_hypercall7(unsigned long cmd, unsigned long in1,
out1, out2, out3, NULL, NULL);
asm_inline volatile (VMWARE_HYPERCALL
- : "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3)
+ : "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3),
+ "+S" (in4), "+D" (in5)
: [port] "i" (VMWARE_HYPERVISOR_PORT),
"a" (VMWARE_HYPERVISOR_MAGIC),
"b" (in1),
"c" (cmd),
- "d" (in3),
- "S" (in4),
- "D" (in5)
+ "d" (in3)
: "cc", "memory");
+
return out0;
}
@@ -272,7 +269,9 @@ unsigned long vmware_hypercall_hb_out(unsigned long cmd, unsigned long in2,
unsigned long in5, unsigned long in6,
u32 *out1)
{
- unsigned long out0;
+ unsigned long out0, port;
+
+ port = in3 | VMWARE_HYPERVISOR_PORT_HB;
asm_inline volatile (
UNWIND_HINT_SAVE
@@ -282,15 +281,13 @@ unsigned long vmware_hypercall_hb_out(unsigned long cmd, unsigned long in2,
"rep outsb\n\t"
"pop %%" _ASM_BP "\n\t"
UNWIND_HINT_RESTORE
- : "=a" (out0), "=b" (*out1)
+ : "=a" (out0), "=b" (*out1), "+c" (in2), "+d" (port),
+ "+S" (in4), "+D" (in5)
: "a" (VMWARE_HYPERVISOR_MAGIC),
"b" (cmd),
- "c" (in2),
- "d" (in3 | VMWARE_HYPERVISOR_PORT_HB),
- "S" (in4),
- "D" (in5),
[in6] VMW_BP_CONSTRAINT (in6)
: "cc", "memory");
+
return out0;
}
@@ -300,7 +297,9 @@ unsigned long vmware_hypercall_hb_in(unsigned long cmd, unsigned long in2,
unsigned long in5, unsigned long in6,
u32 *out1)
{
- unsigned long out0;
+ unsigned long out0, port;
+
+ port = in3 | VMWARE_HYPERVISOR_PORT_HB;
asm_inline volatile (
UNWIND_HINT_SAVE
@@ -310,13 +309,10 @@ unsigned long vmware_hypercall_hb_in(unsigned long cmd, unsigned long in2,
"rep insb\n\t"
"pop %%" _ASM_BP "\n\t"
UNWIND_HINT_RESTORE
- : "=a" (out0), "=b" (*out1)
+ : "=a" (out0), "=b" (*out1), "+c" (in2), "+d" (port),
+ "+S" (in4), "+D" (in5)
: "a" (VMWARE_HYPERVISOR_MAGIC),
"b" (cmd),
- "c" (in2),
- "d" (in3 | VMWARE_HYPERVISOR_PORT_HB),
- "S" (in4),
- "D" (in5),
[in6] VMW_BP_CONSTRAINT (in6)
: "cc", "memory");
return out0;
--
2.52.0
Hi Josh,
Thanks for reporting the problem.
VMware hypercall 0x27 (VMWARE_CMD_ABSPOINTER_DATA) handler only modifies
(returns data) on the first 4 arguments, regs: RAX, RBX, RCX, RDX.
It does not and should not clobber any other guest registers except CC
state.
From the Oops message, the hardware is QEMU Standard PC.
And the issue is caused by the vmmouse emulation there, specifically in
vmmouse_ioport_read() function.
1. vmmouse_get_data(data) saves lower 32 bit for all 6 args.
https://github.com/qemu/qemu/blob/master/hw/i386/vmmouse.c#L227
2. vmmouse_data() processes the hypercall preparing the data for the
first 4 arguments.
https://github.com/qemu/qemu/blob/master/hw/i386/vmmouse.c#L255
3. vmmouse_set_data(data). Copies only lower 32 bit back to all 6 args
and _zeroes_ upper 32 bits for untouched RDI and RSI.
Workarounding QEMU misbehavior from the kernel side by introducing less
efficient asm inlines does not sound correct.
Please report or fix the issue from QEMU side.
Recommended QEMU fix: vmmouse_get_data/vmmouse_set_data should
save/restore target_ulong type instead of uint32_t.
Regards,
--Alexey
On 1/21/26 7:18 PM, Josh Poimboeuf wrote:
> Fedora QA reported the following panic:
>
> BUG: unable to handle page fault for address: 0000000040003e54
> #PF: supervisor write access in kernel mode
> #PF: error_code(0x0002) - not-present page
> PGD 1082ec067 P4D 0
> Oops: Oops: 0002 [#1] SMP NOPTI
> CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 6.19.0-0.rc4.260108gf0b9d8eb98df.34.fc43.x86_64 #1 PREEMPT(lazy)
> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS edk2-20251119-3.fc43 11/19/2025
> RIP: 0010:vmware_hypercall4.constprop.0+0x52/0x90
> Code: 48 83 c4 20 5b e9 69 f0 fc fe 8b 05 a0 c1 b2 01 85 c0 74 23 b8 68 58 4d 56 b9 27 00 00 00 31 d2 bb 04 00 00 00 66 ba 58 56 ed <89> 1f 89 0e 41 89 10 5b e9 3c f0 fc fe 6a 00 49 89 f9 45 31 c0 31
> RSP: 0018:ff5eeb3240003e40 EFLAGS: 00010046
> RAX: 0000000000000000 RBX: 000000000000ffca RCX: 000000000000ffac
> RDX: 0000000000000000 RSI: 0000000040003e58 RDI: 0000000040003e54
> RBP: ff1e05f3c1204800 R08: ff5eeb3240003e5c R09: 000000009d899c41
> R10: 000000000000003d R11: ff5eeb3240003ff8 R12: 0000000000000000
> R13: 00000000000000ff R14: ff1e05f3c02f9e00 R15: 000000000000000c
> FS: 0000000000000000(0000) GS:ff1e05f489e40000(0000) knlGS:0000000000000000
> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 0000000040003e54 CR3: 000000010841d002 CR4: 0000000000771ef0
> PKRU: 55555554
> Call Trace:
> <IRQ>
> vmmouse_report_events+0x13e/0x1b0
> psmouse_handle_byte+0x15/0x60
> ps2_interrupt+0x8a/0xd0
> ...
>
> The panic was triggered by dereferencing a bad pointer (in RDI)
> immediately after a VMware hypercall:
>
> ffffffff82135070 <vmware_hypercall4.constprop.0>:
> ...
> ffffffff821350ac: b8 68 58 4d 56 mov $0x564d5868,%eax
> ffffffff821350b1: b9 27 00 00 00 mov $0x27,%ecx
> ffffffff821350b6: 31 d2 xor %edx,%edx
> ffffffff821350b8: bb 04 00 00 00 mov $0x4,%ebx
> ffffffff821350bd: 66 ba 58 56 mov $0x5658,%dx
> ffffffff821350c1: ed in (%dx),%eax <-- hypercall
> ffffffff821350c2: 89 1f mov %ebx,(%rdi) <-- crash
>
> Reading the disassembly shows that RDI should contain the value of a
> valid kernel stack address here (0xff5eeb3240003e54). Instead it
> contains 0x40003e54, suggesting the hypervisor cleared the upper 32
> bits.
>
> This issue was bisected to commit aca282ab7e75 ("x86/asm: Annotate
> special section entries"), which added annotations to the ALTERNATIVE()
> macro. Despite the use of asm_inline, that commit caused the compiler
> to un-inline and const-propagate vmware_hypercall4().
>
> That made RDI live across the hypercall, making the hypervisor's
> register clobbering visible and exposing this latent bug.
>
> The open-vm-tools reference implementation treats all six registers as
> clobbered for all hypercalls. Match that behavior here.
>
> Fixes: 34bf25e820ae ("x86/vmware: Introduce VMware hypercall API")
> Fixes: aca282ab7e75 ("x86/asm: Annotate special section entries")
> Reported-by: Justin Forbes <jforbes@fedoraproject.org>
> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
> ---
> arch/x86/include/asm/vmware.h | 72 +++++++++++++++++------------------
> 1 file changed, 34 insertions(+), 38 deletions(-)
>
> diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h
> index c9cf43d5ef23..372173d4ea27 100644
> --- a/arch/x86/include/asm/vmware.h
> +++ b/arch/x86/include/asm/vmware.h
> @@ -98,7 +98,7 @@ extern unsigned long vmware_tdx_hypercall(unsigned long cmd,
> static inline
> unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1)
> {
> - unsigned long out0;
> + unsigned long out0, tmp = 0;
>
> if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
> return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
> @@ -109,13 +109,11 @@ unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1)
> NULL, NULL, NULL, NULL, NULL);
>
> asm_inline volatile (VMWARE_HYPERCALL
> - : "=a" (out0)
> + : "=a" (out0), "+b" (in1), "+c" (cmd), "+d" (tmp)
> : [port] "i" (VMWARE_HYPERVISOR_PORT),
> - "a" (VMWARE_HYPERVISOR_MAGIC),
> - "b" (in1),
> - "c" (cmd),
> - "d" (0)
> - : "cc", "memory");
> + "a" (VMWARE_HYPERVISOR_MAGIC)
> + : "di", "si", "cc", "memory");
> +
> return out0;
> }
>
> @@ -123,7 +121,7 @@ static inline
> unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1,
> u32 *out1, u32 *out2)
> {
> - unsigned long out0;
> + unsigned long out0, tmp = 0;
>
> if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
> return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
> @@ -134,13 +132,13 @@ unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1,
> out1, out2, NULL, NULL, NULL);
>
> asm_inline volatile (VMWARE_HYPERCALL
> - : "=a" (out0), "=b" (*out1), "=c" (*out2)
> + : "=a" (out0), "=b" (*out1), "=c" (*out2), "+d" (tmp)
> : [port] "i" (VMWARE_HYPERVISOR_PORT),
> "a" (VMWARE_HYPERVISOR_MAGIC),
> "b" (in1),
> - "c" (cmd),
> - "d" (0)
> - : "cc", "memory");
> + "c" (cmd)
> + : "di", "si", "cc", "memory");
> +
> return out0;
> }
>
> @@ -165,7 +163,8 @@ unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1,
> "b" (in1),
> "c" (cmd),
> "d" (0)
> - : "cc", "memory");
> + : "di", "si", "cc", "memory");
> +
> return out0;
> }
>
> @@ -185,15 +184,13 @@ unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1,
> NULL, out2, NULL, NULL, NULL);
>
> asm_inline volatile (VMWARE_HYPERCALL
> - : "=a" (out0), "=c" (*out2)
> + : "=a" (out0), "+b" (in1), "=c" (*out2), "+d" (in3),
> + "+S" (in4), "+D" (in5)
> : [port] "i" (VMWARE_HYPERVISOR_PORT),
> "a" (VMWARE_HYPERVISOR_MAGIC),
> - "b" (in1),
> - "c" (cmd),
> - "d" (in3),
> - "S" (in4),
> - "D" (in5)
> + "c" (cmd)
> : "cc", "memory");
> +
> return out0;
> }
>
> @@ -213,14 +210,14 @@ unsigned long vmware_hypercall6(unsigned long cmd, unsigned long in1,
> NULL, out2, out3, out4, out5);
>
> asm_inline volatile (VMWARE_HYPERCALL
> - : "=a" (out0), "=c" (*out2), "=d" (*out3), "=S" (*out4),
> - "=D" (*out5)
> + : "=a" (out0), "+b" (in1), "=c" (*out2), "=d" (*out3),
> + "=S" (*out4), "=D" (*out5)
> : [port] "i" (VMWARE_HYPERVISOR_PORT),
> "a" (VMWARE_HYPERVISOR_MAGIC),
> - "b" (in1),
> "c" (cmd),
> "d" (in3)
> : "cc", "memory");
> +
> return out0;
> }
>
> @@ -241,15 +238,15 @@ unsigned long vmware_hypercall7(unsigned long cmd, unsigned long in1,
> out1, out2, out3, NULL, NULL);
>
> asm_inline volatile (VMWARE_HYPERCALL
> - : "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3)
> + : "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3),
> + "+S" (in4), "+D" (in5)
> : [port] "i" (VMWARE_HYPERVISOR_PORT),
> "a" (VMWARE_HYPERVISOR_MAGIC),
> "b" (in1),
> "c" (cmd),
> - "d" (in3),
> - "S" (in4),
> - "D" (in5)
> + "d" (in3)
> : "cc", "memory");
> +
> return out0;
> }
>
> @@ -272,7 +269,9 @@ unsigned long vmware_hypercall_hb_out(unsigned long cmd, unsigned long in2,
> unsigned long in5, unsigned long in6,
> u32 *out1)
> {
> - unsigned long out0;
> + unsigned long out0, port;
> +
> + port = in3 | VMWARE_HYPERVISOR_PORT_HB;
>
> asm_inline volatile (
> UNWIND_HINT_SAVE
> @@ -282,15 +281,13 @@ unsigned long vmware_hypercall_hb_out(unsigned long cmd, unsigned long in2,
> "rep outsb\n\t"
> "pop %%" _ASM_BP "\n\t"
> UNWIND_HINT_RESTORE
> - : "=a" (out0), "=b" (*out1)
> + : "=a" (out0), "=b" (*out1), "+c" (in2), "+d" (port),
> + "+S" (in4), "+D" (in5)
> : "a" (VMWARE_HYPERVISOR_MAGIC),
> "b" (cmd),
> - "c" (in2),
> - "d" (in3 | VMWARE_HYPERVISOR_PORT_HB),
> - "S" (in4),
> - "D" (in5),
> [in6] VMW_BP_CONSTRAINT (in6)
> : "cc", "memory");
> +
> return out0;
> }
>
> @@ -300,7 +297,9 @@ unsigned long vmware_hypercall_hb_in(unsigned long cmd, unsigned long in2,
> unsigned long in5, unsigned long in6,
> u32 *out1)
> {
> - unsigned long out0;
> + unsigned long out0, port;
> +
> + port = in3 | VMWARE_HYPERVISOR_PORT_HB;
>
> asm_inline volatile (
> UNWIND_HINT_SAVE
> @@ -310,13 +309,10 @@ unsigned long vmware_hypercall_hb_in(unsigned long cmd, unsigned long in2,
> "rep insb\n\t"
> "pop %%" _ASM_BP "\n\t"
> UNWIND_HINT_RESTORE
> - : "=a" (out0), "=b" (*out1)
> + : "=a" (out0), "=b" (*out1), "+c" (in2), "+d" (port),
> + "+S" (in4), "+D" (in5)
> : "a" (VMWARE_HYPERVISOR_MAGIC),
> "b" (cmd),
> - "c" (in2),
> - "d" (in3 | VMWARE_HYPERVISOR_PORT_HB),
> - "S" (in4),
> - "D" (in5),
> [in6] VMW_BP_CONSTRAINT (in6)
> : "cc", "memory");
> return out0;
[CCing the regression list]
On 1/22/26 11:00, Alexey Makhalov wrote:
>
> Thanks for reporting the problem.
> [...]
> Workarounding QEMU misbehavior from the kernel side by introducing less
> efficient asm inlines does not sound correct.
Well, fixing bugs right where they are obviously is a good thing.
But well, the problem according to the description quoted below was
exposed by a change that went into 6.19-rc1 -- which makes it a kernel
regression that must be fixed in the kernel (ideally before 6.19 is out).
At least from my understanding of Linus point of view on situations like
that. Or am I mistaken for some reason?
Or is this a case of "we for now assume this is such a corner case that
nobody else will hit; if we are wrong we'll reconsider".
Ciao, Thorsten
> Please report or fix the issue from QEMU side.
> Recommended QEMU fix: vmmouse_get_data/vmmouse_set_data should save/
> restore target_ulong type instead of uint32_t.
>
> Regards,
> --Alexey
>
> On 1/21/26 7:18 PM, Josh Poimboeuf wrote:
>> Fedora QA reported the following panic:
>>
>> BUG: unable to handle page fault for address: 0000000040003e54
>> #PF: supervisor write access in kernel mode
>> #PF: error_code(0x0002) - not-present page
>> PGD 1082ec067 P4D 0
>> Oops: Oops: 0002 [#1] SMP NOPTI
>> CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted
>> 6.19.0-0.rc4.260108gf0b9d8eb98df.34.fc43.x86_64 #1 PREEMPT(lazy)
>> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS
>> edk2-20251119-3.fc43 11/19/2025
>> RIP: 0010:vmware_hypercall4.constprop.0+0x52/0x90
>> Code: 48 83 c4 20 5b e9 69 f0 fc fe 8b 05 a0 c1 b2 01 85 c0 74 23
>> b8 68 58 4d 56 b9 27 00 00 00 31 d2 bb 04 00 00 00 66 ba 58 56 ed <89>
>> 1f 89 0e 41 89 10 5b e9 3c f0 fc fe 6a 00 49 89 f9 45 31 c0 31
>> RSP: 0018:ff5eeb3240003e40 EFLAGS: 00010046
>> RAX: 0000000000000000 RBX: 000000000000ffca RCX: 000000000000ffac
>> RDX: 0000000000000000 RSI: 0000000040003e58 RDI: 0000000040003e54
>> RBP: ff1e05f3c1204800 R08: ff5eeb3240003e5c R09: 000000009d899c41
>> R10: 000000000000003d R11: ff5eeb3240003ff8 R12: 0000000000000000
>> R13: 00000000000000ff R14: ff1e05f3c02f9e00 R15: 000000000000000c
>> FS: 0000000000000000(0000) GS:ff1e05f489e40000(0000)
>> knlGS:0000000000000000
>> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>> CR2: 0000000040003e54 CR3: 000000010841d002 CR4: 0000000000771ef0
>> PKRU: 55555554
>> Call Trace:
>> <IRQ>
>> vmmouse_report_events+0x13e/0x1b0
>> psmouse_handle_byte+0x15/0x60
>> ps2_interrupt+0x8a/0xd0
>> ...
>>
>> The panic was triggered by dereferencing a bad pointer (in RDI)
>> immediately after a VMware hypercall:
>>
>> ffffffff82135070 <vmware_hypercall4.constprop.0>:
>> ...
>> ffffffff821350ac: b8 68 58 4d 56 mov $0x564d5868,
>> %eax
>> ffffffff821350b1: b9 27 00 00 00 mov $0x27,%ecx
>> ffffffff821350b6: 31 d2 xor %edx,%edx
>> ffffffff821350b8: bb 04 00 00 00 mov $0x4,%ebx
>> ffffffff821350bd: 66 ba 58 56 mov $0x5658,%dx
>> ffffffff821350c1: ed in (%dx),
>> %eax <-- hypercall
>> ffffffff821350c2: 89 1f mov %ebx,
>> (%rdi) <-- crash
>>
>> Reading the disassembly shows that RDI should contain the value of a
>> valid kernel stack address here (0xff5eeb3240003e54). Instead it
>> contains 0x40003e54, suggesting the hypervisor cleared the upper 32
>> bits.
>>
>> This issue was bisected to commit aca282ab7e75 ("x86/asm: Annotate
>> special section entries"), which added annotations to the ALTERNATIVE()
>> macro. Despite the use of asm_inline, that commit caused the compiler
>> to un-inline and const-propagate vmware_hypercall4().
>>
>> That made RDI live across the hypercall, making the hypervisor's
>> register clobbering visible and exposing this latent bug.
>>
>> The open-vm-tools reference implementation treats all six registers as
>> clobbered for all hypercalls. Match that behavior here.
>>
>> Fixes: 34bf25e820ae ("x86/vmware: Introduce VMware hypercall API")
>> Fixes: aca282ab7e75 ("x86/asm: Annotate special section entries")
>> Reported-by: Justin Forbes <jforbes@fedoraproject.org>
>> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
>> ---
>> arch/x86/include/asm/vmware.h | 72 +++++++++++++++++------------------
>> 1 file changed, 34 insertions(+), 38 deletions(-)
>>
>> diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/
>> vmware.h
>> index c9cf43d5ef23..372173d4ea27 100644
>> --- a/arch/x86/include/asm/vmware.h
>> +++ b/arch/x86/include/asm/vmware.h
>> @@ -98,7 +98,7 @@ extern unsigned long vmware_tdx_hypercall(unsigned
>> long cmd,
>> static inline
>> unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1)
>> {
>> - unsigned long out0;
>> + unsigned long out0, tmp = 0;
>> if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
>> return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
>> @@ -109,13 +109,11 @@ unsigned long vmware_hypercall1(unsigned long
>> cmd, unsigned long in1)
>> NULL, NULL, NULL, NULL, NULL);
>> asm_inline volatile (VMWARE_HYPERCALL
>> - : "=a" (out0)
>> + : "=a" (out0), "+b" (in1), "+c" (cmd), "+d" (tmp)
>> : [port] "i" (VMWARE_HYPERVISOR_PORT),
>> - "a" (VMWARE_HYPERVISOR_MAGIC),
>> - "b" (in1),
>> - "c" (cmd),
>> - "d" (0)
>> - : "cc", "memory");
>> + "a" (VMWARE_HYPERVISOR_MAGIC)
>> + : "di", "si", "cc", "memory");
>> +
>> return out0;
>> }
>> @@ -123,7 +121,7 @@ static inline
>> unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1,
>> u32 *out1, u32 *out2)
>> {
>> - unsigned long out0;
>> + unsigned long out0, tmp = 0;
>> if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
>> return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
>> @@ -134,13 +132,13 @@ unsigned long vmware_hypercall3(unsigned long
>> cmd, unsigned long in1,
>> out1, out2, NULL, NULL, NULL);
>> asm_inline volatile (VMWARE_HYPERCALL
>> - : "=a" (out0), "=b" (*out1), "=c" (*out2)
>> + : "=a" (out0), "=b" (*out1), "=c" (*out2), "+d" (tmp)
>> : [port] "i" (VMWARE_HYPERVISOR_PORT),
>> "a" (VMWARE_HYPERVISOR_MAGIC),
>> "b" (in1),
>> - "c" (cmd),
>> - "d" (0)
>> - : "cc", "memory");
>> + "c" (cmd)
>> + : "di", "si", "cc", "memory");
>> +
>> return out0;
>> }
>> @@ -165,7 +163,8 @@ unsigned long vmware_hypercall4(unsigned long
>> cmd, unsigned long in1,
>> "b" (in1),
>> "c" (cmd),
>> "d" (0)
>> - : "cc", "memory");
>> + : "di", "si", "cc", "memory");
>> +
>> return out0;
>> }
>> @@ -185,15 +184,13 @@ unsigned long vmware_hypercall5(unsigned long
>> cmd, unsigned long in1,
>> NULL, out2, NULL, NULL, NULL);
>> asm_inline volatile (VMWARE_HYPERCALL
>> - : "=a" (out0), "=c" (*out2)
>> + : "=a" (out0), "+b" (in1), "=c" (*out2), "+d" (in3),
>> + "+S" (in4), "+D" (in5)
>> : [port] "i" (VMWARE_HYPERVISOR_PORT),
>> "a" (VMWARE_HYPERVISOR_MAGIC),
>> - "b" (in1),
>> - "c" (cmd),
>> - "d" (in3),
>> - "S" (in4),
>> - "D" (in5)
>> + "c" (cmd)
>> : "cc", "memory");
>> +
>> return out0;
>> }
>> @@ -213,14 +210,14 @@ unsigned long vmware_hypercall6(unsigned long
>> cmd, unsigned long in1,
>> NULL, out2, out3, out4, out5);
>> asm_inline volatile (VMWARE_HYPERCALL
>> - : "=a" (out0), "=c" (*out2), "=d" (*out3), "=S" (*out4),
>> - "=D" (*out5)
>> + : "=a" (out0), "+b" (in1), "=c" (*out2), "=d" (*out3),
>> + "=S" (*out4), "=D" (*out5)
>> : [port] "i" (VMWARE_HYPERVISOR_PORT),
>> "a" (VMWARE_HYPERVISOR_MAGIC),
>> - "b" (in1),
>> "c" (cmd),
>> "d" (in3)
>> : "cc", "memory");
>> +
>> return out0;
>> }
>> @@ -241,15 +238,15 @@ unsigned long vmware_hypercall7(unsigned long
>> cmd, unsigned long in1,
>> out1, out2, out3, NULL, NULL);
>> asm_inline volatile (VMWARE_HYPERCALL
>> - : "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3)
>> + : "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3),
>> + "+S" (in4), "+D" (in5)
>> : [port] "i" (VMWARE_HYPERVISOR_PORT),
>> "a" (VMWARE_HYPERVISOR_MAGIC),
>> "b" (in1),
>> "c" (cmd),
>> - "d" (in3),
>> - "S" (in4),
>> - "D" (in5)
>> + "d" (in3)
>> : "cc", "memory");
>> +
>> return out0;
>> }
>> @@ -272,7 +269,9 @@ unsigned long vmware_hypercall_hb_out(unsigned
>> long cmd, unsigned long in2,
>> unsigned long in5, unsigned long in6,
>> u32 *out1)
>> {
>> - unsigned long out0;
>> + unsigned long out0, port;
>> +
>> + port = in3 | VMWARE_HYPERVISOR_PORT_HB;
>> asm_inline volatile (
>> UNWIND_HINT_SAVE
>> @@ -282,15 +281,13 @@ unsigned long vmware_hypercall_hb_out(unsigned
>> long cmd, unsigned long in2,
>> "rep outsb\n\t"
>> "pop %%" _ASM_BP "\n\t"
>> UNWIND_HINT_RESTORE
>> - : "=a" (out0), "=b" (*out1)
>> + : "=a" (out0), "=b" (*out1), "+c" (in2), "+d" (port),
>> + "+S" (in4), "+D" (in5)
>> : "a" (VMWARE_HYPERVISOR_MAGIC),
>> "b" (cmd),
>> - "c" (in2),
>> - "d" (in3 | VMWARE_HYPERVISOR_PORT_HB),
>> - "S" (in4),
>> - "D" (in5),
>> [in6] VMW_BP_CONSTRAINT (in6)
>> : "cc", "memory");
>> +
>> return out0;
>> }
>> @@ -300,7 +297,9 @@ unsigned long vmware_hypercall_hb_in(unsigned
>> long cmd, unsigned long in2,
>> unsigned long in5, unsigned long in6,
>> u32 *out1)
>> {
>> - unsigned long out0;
>> + unsigned long out0, port;
>> +
>> + port = in3 | VMWARE_HYPERVISOR_PORT_HB;
>> asm_inline volatile (
>> UNWIND_HINT_SAVE
>> @@ -310,13 +309,10 @@ unsigned long vmware_hypercall_hb_in(unsigned
>> long cmd, unsigned long in2,
>> "rep insb\n\t"
>> "pop %%" _ASM_BP "\n\t"
>> UNWIND_HINT_RESTORE
>> - : "=a" (out0), "=b" (*out1)
>> + : "=a" (out0), "=b" (*out1), "+c" (in2), "+d" (port),
>> + "+S" (in4), "+D" (in5)
>> : "a" (VMWARE_HYPERVISOR_MAGIC),
>> "b" (cmd),
>> - "c" (in2),
>> - "d" (in3 | VMWARE_HYPERVISOR_PORT_HB),
>> - "S" (in4),
>> - "D" (in5),
>> [in6] VMW_BP_CONSTRAINT (in6)
>> : "cc", "memory");
>> return out0;
>
On 1/23/26 1:47 AM, Thorsten Leemhuis wrote:
> Well, fixing bugs right where they are obviously is a good thing.
>
> But well, the problem according to the description quoted below was
> exposed by a change that went into 6.19-rc1 -- which makes it a kernel
> regression that must be fixed in the kernel (ideally before 6.19 is out).
The Linux change 34bf25e820ae ("x86/vmware: Introduce VMware hypercall
API") that revealed QEMU issue was introduced not now, but back in June
2024 in v6.11-rc1. Two LTS versions 6.12 and 6.18 have it.
This issue can be triggered only for specific hypercall (usually
statically inlined) and _only_ if compiler keeps rsi/rdi in use during
the hypercall.
The proposed kernel fix forces compiler to use memory instead of rsi/rdi
registers for _every_ VMware hypercall. Every VMware hypercall caller
should pay a penalty for QEMU issue, even if it runs on non qemu or
fixed/newer qemu platform.
IMHO, user who faced this issue should be given one choice to fix it -
update QEMU as the system may not be operable with this combination
QEMU+Kernel.
If kernel colleagues still believe it should be also solved from the
kernel side, then my proposal is to perform precise fix by using wider
hypercall just for VMWARE_CMD_ABSPOINTER_DATA:
--- a/drivers/input/mouse/vmmouse.c
+++ b/drivers/input/mouse/vmmouse.c
@@ -145,7 +145,7 @@ static psmouse_ret_t vmmouse_report_events(struct
psmouse *psmouse)
}
/* Now get it */
- status = vmware_hypercall4(VMWARE_CMD_ABSPOINTER_DATA, 4,
+ status = vmware_hypercall7(VMWARE_CMD_ABSPOINTER_DATA,
4, 0, 0, 0,
&x, &y, &z);
/*
Regards,
--Alexey
On 1/24/26 02:01, Alexey Makhalov wrote:
> On 1/23/26 1:47 AM, Thorsten Leemhuis wrote:
>> Well, fixing bugs right where they are obviously is a good thing.
>>
>> But well, the problem according to the description quoted below was
>> exposed by a change that went into 6.19-rc1 -- which makes it a kernel
>> regression that must be fixed in the kernel (ideally before 6.19 is out).
>
> The Linux change 34bf25e820ae ("x86/vmware: Introduce VMware hypercall
> API") that revealed QEMU issue was introduced not now, but back in June
> 2024 in v6.11-rc1. [...]
Well, the patch at the start of the thread has two fixes tags – and I
meant the other one referring to aca282ab7e75 ("x86/asm: Annotate
special section entries"), which was merged for 6.19-rc1. And the
description of the patch at the start of this thread also reads ""This
issue was bisected to commit aca282ab7e75 ("x86/asm: Annotate special
section entries"), which added annotations to the ALTERNATIVE() macro.
Despite the use of asm_inline, that commit caused the compiler to
un-inline and const-propagate vmware_hypercall4(). That made RDI live
across the hypercall, making the hypervisor's register clobbering
visible and exposing this latent bug.""
Ciao, Thorsten
On Fri, Jan 23, 2026 at 10:47:18AM +0100, Thorsten Leemhuis wrote: > [CCing the regression list] > > On 1/22/26 11:00, Alexey Makhalov wrote: > > > > Thanks for reporting the problem. > > [...] > > Workarounding QEMU misbehavior from the kernel side by introducing less > > efficient asm inlines does not sound correct. > > Well, fixing bugs right where they are obviously is a good thing. > > But well, the problem according to the description quoted below was > exposed by a change that went into 6.19-rc1 -- which makes it a kernel > regression that must be fixed in the kernel (ideally before 6.19 is out). > > At least from my understanding of Linus point of view on situations like > that. Or am I mistaken for some reason? > > Or is this a case of "we for now assume this is such a corner case that > nobody else will hit; if we are wrong we'll reconsider". Hm, yes, from that perspective I agree this is a kernel regression that needs fixed. We still want Linux to work with older "broken" versions of qemu that clobber registers. -- Josh
[CCing Linus, maybe we still can get this fixed for -rc8 or at least final]
On 1/23/26 18:35, Josh Poimboeuf wrote:
> On Fri, Jan 23, 2026 at 10:47:18AM +0100, Thorsten Leemhuis wrote:
>> [CCing the regression list]
>>
>> On 1/22/26 11:00, Alexey Makhalov wrote:
>>>
>>> Thanks for reporting the problem.
>>> [...]
>>> Workarounding QEMU misbehavior from the kernel side by introducing less
>>> efficient asm inlines does not sound correct.
>>
>> Well, fixing bugs right where they are obviously is a good thing.
>>
>> But well, the problem according to the description quoted below was
>> exposed by a change that went into 6.19-rc1 -- which makes it a kernel
>> regression that must be fixed in the kernel (ideally before 6.19 is out).
>>
>> At least from my understanding of Linus point of view on situations like
>> that. Or am I mistaken for some reason?
>>
>> Or is this a case of "we for now assume this is such a corner case that
>> nobody else will hit; if we are wrong we'll reconsider".
>
> Hm, yes, from that perspective I agree this is a kernel regression that
> needs fixed. We still want Linux to work with older "broken" versions
> of qemu that clobber registers.
Josh, what's the status here? From here it looks like nothing happened
during the last week. Should we move on with the patch at the start of
this thread? Or is "widening the hypercall just for
VMWARE_CMD_ABSPOINTER_DATA" as suggested by Alexey elsewhere in this
thread a better fix? Or would temporarily reverting aca282ab7e75
("x86/asm: Annotate special section entries") be the best move for now?
Ciao, Thorsten
On Fri, Jan 30, 2026 at 05:24:02PM +0100, Thorsten Leemhuis wrote:
> [CCing Linus, maybe we still can get this fixed for -rc8 or at least final]
>
> On 1/23/26 18:35, Josh Poimboeuf wrote:
> > On Fri, Jan 23, 2026 at 10:47:18AM +0100, Thorsten Leemhuis wrote:
> >> [CCing the regression list]
> >>
> >> On 1/22/26 11:00, Alexey Makhalov wrote:
> >>>
> >>> Thanks for reporting the problem.
> >>> [...]
> >>> Workarounding QEMU misbehavior from the kernel side by introducing less
> >>> efficient asm inlines does not sound correct.
> >>
> >> Well, fixing bugs right where they are obviously is a good thing.
> >>
> >> But well, the problem according to the description quoted below was
> >> exposed by a change that went into 6.19-rc1 -- which makes it a kernel
> >> regression that must be fixed in the kernel (ideally before 6.19 is out).
> >>
> >> At least from my understanding of Linus point of view on situations like
> >> that. Or am I mistaken for some reason?
> >>
> >> Or is this a case of "we for now assume this is such a corner case that
> >> nobody else will hit; if we are wrong we'll reconsider".
> >
> > Hm, yes, from that perspective I agree this is a kernel regression that
> > needs fixed. We still want Linux to work with older "broken" versions
> > of qemu that clobber registers.
>
> Josh, what's the status here? From here it looks like nothing happened
> during the last week. Should we move on with the patch at the start of
> this thread? Or is "widening the hypercall just for
> VMWARE_CMD_ABSPOINTER_DATA" as suggested by Alexey elsewhere in this
> thread a better fix? Or would temporarily reverting aca282ab7e75
> ("x86/asm: Annotate special section entries") be the best move for now?
I think we still need to go with the original patch at the start of this
thread. There's nothing preventing the compiler from doing similar
optimizations for the other hypercalls.
--
Josh
On Fri, Jan 30 2026 at 08:46, Josh Poimboeuf wrote:
> On Fri, Jan 30, 2026 at 05:24:02PM +0100, Thorsten Leemhuis wrote:
>> >>> Workarounding QEMU misbehavior from the kernel side by introducing less
>> >>> efficient asm inlines does not sound correct.
>> >>
>> >> Well, fixing bugs right where they are obviously is a good thing.
>> >>
>> >> But well, the problem according to the description quoted below was
>> >> exposed by a change that went into 6.19-rc1 -- which makes it a kernel
>> >> regression that must be fixed in the kernel (ideally before 6.19 is out).
>> >>
>> >> At least from my understanding of Linus point of view on situations like
>> >> that. Or am I mistaken for some reason?
>> >>
>> >> Or is this a case of "we for now assume this is such a corner case that
>> >> nobody else will hit; if we are wrong we'll reconsider".
>> >
>> > Hm, yes, from that perspective I agree this is a kernel regression that
>> > needs fixed. We still want Linux to work with older "broken" versions
>> > of qemu that clobber registers.
>>
>> Josh, what's the status here? From here it looks like nothing happened
>> during the last week. Should we move on with the patch at the start of
>> this thread? Or is "widening the hypercall just for
>> VMWARE_CMD_ABSPOINTER_DATA" as suggested by Alexey elsewhere in this
>> thread a better fix? Or would temporarily reverting aca282ab7e75
>> ("x86/asm: Annotate special section entries") be the best move for now?
>
> I think we still need to go with the original patch at the start of this
> thread. There's nothing preventing the compiler from doing similar
> optimizations for the other hypercalls.
That's correct, but not a problem as long as the hypercall does not
clobber registers beyond those which are in use for a particular
hypercall, no?
Unfortunately there is no formal specification of the hypercall
(backdoor) ABI available, which VMWare really should provide.
All what's available is the lazy 'fits all sizes' implementation in
open-vm-tools and the optimized kernel variant.
The latter makes it pretty obvious that at least the VMWare hypervisor
is handling it correctly. Otherwise we'd have seen reports by now.
As the issue seems to be restricted to an already identified Qemu bug,
it is overkill to penalize perfectly working systems by making all
hypercalls more expensive than necessary.
So unless there is a compelling argument why the existing hypercall
implementation is broken by design, the trivial one-line fix from Alexey
is addressing the actual root cause (it just needs a big fat comment)
and good enough to cure the regression, no?
Alternatively if you don't trust the QEMU/KVM emulation of the VMWare
backdoor at all then force switch it to the slow path and let VMWare
use the optimized inlines.
Thanks,
tglx
On Fri, Feb 06, 2026 at 11:07:22AM +0100, Thomas Gleixner wrote:
> So unless there is a compelling argument why the existing hypercall
> implementation is broken by design, the trivial one-line fix from Alexey
> is addressing the actual root cause (it just needs a big fat comment)
> and good enough to cure the regression, no?
While my original patch might be overkill, Alexey's one-line fix doesn't
go far enough:
1) It only changes one hypercall site, the vmmouse driver has several.
All of the following commands are subject to register corruption by
QEMU:
VMWARE_CMD_ABSPOINTER_DATA
VMWARE_CMD_ABSPOINTER_STATUS
VMWARE_CMD_ABSPOINTER_COMMAND
2) While the inline asm for vmware_hypercall7() does have RSI/RDI
listed as input constraints, it doesn't clobber them.
So a spot fix would need to be something like so:
diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h
index c9cf43d5ef23..9f72569fc8c2 100644
--- a/arch/x86/include/asm/vmware.h
+++ b/arch/x86/include/asm/vmware.h
@@ -119,6 +119,27 @@ unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1)
return out0;
}
+static inline
+unsigned long vmware_hypercall1_clobber(unsigned long cmd, unsigned long in1)
+{
+ unsigned long out0, tmp = 0;
+
+ if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
+ return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
+ NULL, NULL, NULL, NULL, NULL);
+
+ if (unlikely(!alternatives_patched) && !__is_defined(MODULE))
+ return vmware_hypercall_slow(cmd, in1, 0, 0, 0,
+ NULL, NULL, NULL, NULL, NULL);
+
+ asm_inline volatile (VMWARE_HYPERCALL
+ : "=a" (out0), "+b" (in1), "+c" (cmd), "+d" (tmp)
+ : [port] "i" (VMWARE_HYPERVISOR_PORT),
+ "a" (VMWARE_HYPERVISOR_MAGIC)
+ : "di", "si", "cc", "memory");
+ return out0;
+}
+
static inline
unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1,
u32 *out1, u32 *out2)
@@ -144,6 +165,30 @@ unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1,
return out0;
}
+static inline
+unsigned long vmware_hypercall3_clobber(unsigned long cmd, unsigned long in1,
+ u32 *out1, u32 *out2)
+{
+ unsigned long out0, tmp = 0;
+
+ if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
+ return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
+ out1, out2, NULL, NULL, NULL);
+
+ if (unlikely(!alternatives_patched) && !__is_defined(MODULE))
+ return vmware_hypercall_slow(cmd, in1, 0, 0, 0,
+ out1, out2, NULL, NULL, NULL);
+
+ asm_inline volatile (VMWARE_HYPERCALL
+ : "=a" (out0), "=b" (*out1), "=c" (*out2), "+d" (tmp)
+ : [port] "i" (VMWARE_HYPERVISOR_PORT),
+ "a" (VMWARE_HYPERVISOR_MAGIC),
+ "b" (in1),
+ "c" (cmd)
+ : "di", "si", "cc", "memory");
+ return out0;
+}
+
static inline
unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1,
u32 *out1, u32 *out2, u32 *out3)
@@ -169,6 +214,31 @@ unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1,
return out0;
}
+static inline
+unsigned long vmware_hypercall4_clobber(unsigned long cmd, unsigned long in1,
+ u32 *out1, u32 *out2, u32 *out3)
+{
+ unsigned long out0;
+
+ if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
+ return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
+ out1, out2, out3, NULL, NULL);
+
+ if (unlikely(!alternatives_patched) && !__is_defined(MODULE))
+ return vmware_hypercall_slow(cmd, in1, 0, 0, 0,
+ out1, out2, out3, NULL, NULL);
+
+ asm_inline volatile (VMWARE_HYPERCALL
+ : "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3)
+ : [port] "i" (VMWARE_HYPERVISOR_PORT),
+ "a" (VMWARE_HYPERVISOR_MAGIC),
+ "b" (in1),
+ "c" (cmd),
+ "d" (0)
+ : "di", "si", "cc", "memory");
+ return out0;
+}
+
static inline
unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1,
unsigned long in3, unsigned long in4,
diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c
index fb1d986a6895..0ab04b8bb923 100644
--- a/drivers/input/mouse/vmmouse.c
+++ b/drivers/input/mouse/vmmouse.c
@@ -125,7 +125,7 @@ static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse)
while (count--) {
/* See if we have motion data. */
- status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0);
+ status = vmware_hypercall1_clobber(VMWARE_CMD_ABSPOINTER_STATUS, 0);
if ((status & VMMOUSE_ERROR) == VMMOUSE_ERROR) {
psmouse_err(psmouse, "failed to fetch status data\n");
/*
@@ -145,8 +145,8 @@ static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse)
}
/* Now get it */
- status = vmware_hypercall4(VMWARE_CMD_ABSPOINTER_DATA, 4,
- &x, &y, &z);
+ status = vmware_hypercall4_clobber(VMWARE_CMD_ABSPOINTER_DATA, 4,
+ &x, &y, &z);
/*
* And report what we've got. Prefer to report button
@@ -222,9 +222,9 @@ static void vmmouse_disable(struct psmouse *psmouse)
{
u32 status;
- vmware_hypercall1(VMWARE_CMD_ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE);
+ vmware_hypercall1_clobber(VMWARE_CMD_ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE);
- status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0);
+ status = vmware_hypercall1_clobber(VMWARE_CMD_ABSPOINTER_STATUS, 0);
if ((status & VMMOUSE_ERROR) != VMMOUSE_ERROR)
psmouse_warn(psmouse, "failed to disable vmmouse device\n");
}
@@ -246,19 +246,19 @@ static int vmmouse_enable(struct psmouse *psmouse)
* Try enabling the device. If successful, we should be able to
* read valid version ID back from it.
*/
- vmware_hypercall1(VMWARE_CMD_ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE);
+ vmware_hypercall1_clobber(VMWARE_CMD_ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE);
/*
* See if version ID can be retrieved.
*/
- status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0);
+ status = vmware_hypercall1_clobber(VMWARE_CMD_ABSPOINTER_STATUS, 0);
if ((status & 0x0000ffff) == 0) {
psmouse_dbg(psmouse, "empty flags - assuming no device\n");
return -ENXIO;
}
- version = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_DATA,
- 1 /* single item */);
+ version = vmware_hypercall1_clobber(VMWARE_CMD_ABSPOINTER_DATA,
+ 1 /* single item */);
if (version != VMMOUSE_VERSION_ID) {
psmouse_dbg(psmouse, "Unexpected version value: %u vs %u\n",
(unsigned) version, VMMOUSE_VERSION_ID);
@@ -269,11 +269,10 @@ static int vmmouse_enable(struct psmouse *psmouse)
/*
* Restrict ioport access, if possible.
*/
- vmware_hypercall1(VMWARE_CMD_ABSPOINTER_RESTRICT,
- VMMOUSE_RESTRICT_CPL0);
+ vmware_hypercall1(VMWARE_CMD_ABSPOINTER_RESTRICT, VMMOUSE_RESTRICT_CPL0);
- vmware_hypercall1(VMWARE_CMD_ABSPOINTER_COMMAND,
- VMMOUSE_CMD_REQUEST_ABSOLUTE);
+ vmware_hypercall1_clobber(VMWARE_CMD_ABSPOINTER_COMMAND,
+ VMMOUSE_CMD_REQUEST_ABSOLUTE);
return 0;
}
@@ -320,7 +319,7 @@ int vmmouse_detect(struct psmouse *psmouse, bool set_properties)
/* Check if the device is present */
response = ~VMWARE_HYPERVISOR_MAGIC;
- version = vmware_hypercall3(VMWARE_CMD_GETVERSION, 0, &response, &type);
+ version = vmware_hypercall3_clobber(VMWARE_CMD_GETVERSION, 0, &response, &type);
if (response != VMWARE_HYPERVISOR_MAGIC || version == 0xffffffffU)
return -ENXIO;
,
On Fri, 6 Feb 2026 at 08:32, Josh Poimboeuf <jpoimboe@kernel.org> wrote:
>
> So a spot fix would need to be something like so:
So from what I can tell, this was never a kernel bug to begin with,
and the actual bug is in QEMU. And the kernel change that exposes this
is old, and apparently the main issue is that it also then depends on
bad luck with a compiler that generates particular code that then
shows the QEMU bug.
So what I'd suggest we do is to do the *minimal* workaround for the
specific case of the broken QEMU mouse emulation, and not make the
already ugly vmware code even worse like your patch.
And the minimal workaround is apparently just the
vmmouse_report_events() oneliner that Alexey Makhalov suggested.
Longer term, we should probably clean this garbage up. The whole "use
inline functions with inline asm" for the vmware case makes zero sense
to begin with. Absolutely nobody cares. This is not
performance-critical code. We should get rid of those inlines in
<asm/vmware.h> *entirely*, and just make vmware_hypercall_slow() be
less of a shit-show.
Make that stupid switch statement in vmware_hypercall_slow() use a
static call, and get rid of the idiotic calling conventions that pass
in ten arguments, of which five are pointers that can be NULL. So
*OF*COURSE* the end result is a steaming pile of sh*t because the
calling convention is just a pile of dung that cannot be dealt with
well.
So make it do something like this instead:
// Called 'in1,3-5' traditionally for bad reasons.
// 'in2' was presumably apparently 'cmd' in cx
// and ax is VMWARE_HYPERVISOR_MAGIC
struct vmware_hypercall_args {
unsigned long bx, dx, si, di;
};
// Called 'out1-5' traditionally for bad reasons.
// 'in0' is returned in ax.
struct vmware_hypercall_results {
unsigned long bx, cx, dx, si, di;
};
unsigned long vmware_hypercall(unsigned long cmd,
const struct vmware_hypercall_args *in,
struct vmware_hypercall_results *out)
{
... do sane code here ...
and I can almost guarantee it's going to be as fast or faster than the
existing crazy inline asm, because it won't have any stupid bad
calling conventions.
Then you can have trivial wrapper functions like
static inline unsigned long vmware_hypercall1(unsigned long
cmd, unsigned long arg)
{
const struct vmware_hypercall_args in = { .bx = arg };
struct vmware_hypercall_results out;
return vmware_hypercall(cmd, &in, &out);
}
and you're damn well done. Wouldn't that be a hell of a lot nicer -
and avoid the existing bug just by virtue of not having that stupid
and pointless "optimziation" where it thinks that si/di might be
useful around the vmware call.
The existing vmware code is just disgusting. Don't try to "fix it up"
for a bug that isn't even in the kernel.
Please.
Linus
On 2/6/26 9:19 AM, Linus Torvalds wrote:
>
> Longer term, we should probably clean this garbage up. The whole "use
> inline functions with inline asm" for the vmware case makes zero sense
> to begin with. Absolutely nobody cares. This is not
> performance-critical code. We should get rid of those inlines in
> <asm/vmware.h> *entirely*, and just make vmware_hypercall_slow() be
> less of a shit-show.
>
> Make that stupid switch statement in vmware_hypercall_slow() use a
> static call, and get rid of the idiotic calling conventions that pass
> in ten arguments, of which five are pointers that can be NULL. So
> *OF*COURSE* the end result is a steaming pile of sh*t because the
> calling convention is just a pile of dung that cannot be dealt with
> well.
>
> So make it do something like this instead:
>
> // Called 'in1,3-5' traditionally for bad reasons.
> // 'in2' was presumably apparently 'cmd' in cx
> // and ax is VMWARE_HYPERVISOR_MAGIC
> struct vmware_hypercall_args {
> unsigned long bx, dx, si, di;
> };
>
> // Called 'out1-5' traditionally for bad reasons.
> // 'in0' is returned in ax.
> struct vmware_hypercall_results {
> unsigned long bx, cx, dx, si, di;
> };
>
> unsigned long vmware_hypercall(unsigned long cmd,
> const struct vmware_hypercall_args *in,
> struct vmware_hypercall_results *out)
> {
> ... do sane code here ...
>
> and I can almost guarantee it's going to be as fast or faster than the
> existing crazy inline asm, because it won't have any stupid bad
> calling conventions.
>
> Then you can have trivial wrapper functions like
>
> static inline unsigned long vmware_hypercall1(unsigned long
> cmd, unsigned long arg)
> {
> const struct vmware_hypercall_args in = { .bx = arg };
> struct vmware_hypercall_results out;
> return vmware_hypercall(cmd, &in, &out);
> }
>
> and you're damn well done. Wouldn't that be a hell of a lot nicer -
> and avoid the existing bug just by virtue of not having that stupid
> and pointless "optimziation" where it thinks that si/di might be
> useful around the vmware call.
>
Thanks, Linus, for the suggestion.
vmware_hypercallX family of functions follows the idea of kvm_hypercallX
from <asm/kvm_para.h>. But legacy and variations of possible
combinations made it hairy.
Having just one wide hypercall implementation and multiple wrappers will
definitely be more readable and maintainable. Questionable about
performance though.
I'll work on it.
We will also analyze the possibility of the backdoor deprecation from
the Linux kernel side.
--Alexey
On Fri, Feb 06, 2026 at 09:19:05AM -0800, Linus Torvalds wrote: > , > > On Fri, 6 Feb 2026 at 08:32, Josh Poimboeuf <jpoimboe@kernel.org> wrote: > > > > So a spot fix would need to be something like so: > > So from what I can tell, this was never a kernel bug to begin with, > and the actual bug is in QEMU. And the kernel change that exposes this > is old, and apparently the main issue is that it also then depends on > bad luck with a compiler that generates particular code that then > shows the QEMU bug. > > So what I'd suggest we do is to do the *minimal* workaround for the > specific case of the broken QEMU mouse emulation, and not make the > already ugly vmware code even worse like your patch. > > And the minimal workaround is apparently just the > vmmouse_report_events() oneliner that Alexey Makhalov suggested. So even if we want to use the strategy of only protecting against those compiler optimizations which we've seen with our own eyes, that one-liner still isn't enough... Looking at the binary, in addition to that vmware_hypercall4.constprop.4 keeping RDI/RSI live across the hypercall, there's a vmware_hypercall3.constprop.0 doing the exact same thing: 0000000000000130 <vmware_hypercall3.constprop.0>: ... 179: ed in (%dx),%eax 17a: 89 1f mov %ebx,(%rdi) 17c: 89 0e mov %ecx,(%rsi) 17e: 5b pop %rbx 17f: e9 00 00 00 00 jmp 184 <vmware_hypercall3.constprop.0+0x54> 180: R_X86_64_PLT32 __x86_return_thunk-0x4 So that's a 2nd hypercall site we'd need to fix. BTW, I suspect the non-inline + constprop madness is caused by the use of CONFIG_DEBUG_SECTION_MISMATCH which adds -fno-inline-functions-called-once. I would love to get rid of that config option, it creates a lot of grief for me personally. Anyway, how about just adding RDI/RSI to the clobbers list for those two hypercalls? It shouldn't have much of an impact on other sites anyway, it should be rare for the compiler to want to keep di/si live in general. diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h index c9cf43d5ef23..4220dae14a2d 100644 --- a/arch/x86/include/asm/vmware.h +++ b/arch/x86/include/asm/vmware.h @@ -140,7 +140,7 @@ unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1, "b" (in1), "c" (cmd), "d" (0) - : "cc", "memory"); + : "di", "si", "cc", "memory"); return out0; } @@ -165,7 +165,7 @@ unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1, "b" (in1), "c" (cmd), "d" (0) - : "cc", "memory"); + : "di", "si", "cc", "memory"); return out0; }
On Fri, 6 Feb 2026 at 11:08, Josh Poimboeuf <jpoimboe@kernel.org> wrote:
>
> Anyway, how about just adding RDI/RSI to the clobbers list for those two
> hypercalls?
Ack, that looks fine and code generation differences would be pretty minimal.
Mind sending a sign-off and I'll apply it and we can forget about this
unless somebody wants to actually clean up that vmware horror later?
Linus
On Fri, Feb 06, 2026 at 11:57:04AM -0800, Linus Torvalds wrote:
> On Fri, 6 Feb 2026 at 11:08, Josh Poimboeuf <jpoimboe@kernel.org> wrote:
> >
> > Anyway, how about just adding RDI/RSI to the clobbers list for those two
> > hypercalls?
>
> Ack, that looks fine and code generation differences would be pretty minimal.
>
> Mind sending a sign-off and I'll apply it and we can forget about this
> unless somebody wants to actually clean up that vmware horror later?
Here ya go:
---8<---
From: Josh Poimboeuf <jpoimboe@kernel.org>
Subject: [PATCH] x86/vmware: Fix vmmouse hypercall clobbers
Fedora QA reported the following panic:
BUG: unable to handle page fault for address: 0000000040003e54
#PF: supervisor write access in kernel mode
#PF: error_code(0x0002) - not-present page
PGD 1082ec067 P4D 0
Oops: Oops: 0002 [#1] SMP NOPTI
CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 6.19.0-0.rc4.260108gf0b9d8eb98df.34.fc43.x86_64 #1 PREEMPT(lazy)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS edk2-20251119-3.fc43 11/19/2025
RIP: 0010:vmware_hypercall4.constprop.0+0x52/0x90
Code: 48 83 c4 20 5b e9 69 f0 fc fe 8b 05 a0 c1 b2 01 85 c0 74 23 b8 68 58 4d 56 b9 27 00 00 00 31 d2 bb 04 00 00 00 66 ba 58 56 ed <89> 1f 89 0e 41 89 10 5b e9 3c f0 fc fe 6a 00 49 89 f9 45 31 c0 31
RSP: 0018:ff5eeb3240003e40 EFLAGS: 00010046
RAX: 0000000000000000 RBX: 000000000000ffca RCX: 000000000000ffac
RDX: 0000000000000000 RSI: 0000000040003e58 RDI: 0000000040003e54
RBP: ff1e05f3c1204800 R08: ff5eeb3240003e5c R09: 000000009d899c41
R10: 000000000000003d R11: ff5eeb3240003ff8 R12: 0000000000000000
R13: 00000000000000ff R14: ff1e05f3c02f9e00 R15: 000000000000000c
FS: 0000000000000000(0000) GS:ff1e05f489e40000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000040003e54 CR3: 000000010841d002 CR4: 0000000000771ef0
PKRU: 55555554
Call Trace:
<IRQ>
vmmouse_report_events+0x13e/0x1b0
psmouse_handle_byte+0x15/0x60
ps2_interrupt+0x8a/0xd0
...
It was triggered by dereferencing a bad pointer (in RDI) immediately
after a VMware hypercall:
ffffffff82135070 <vmware_hypercall4.constprop.0>:
...
ffffffff821350ac: b8 68 58 4d 56 mov $0x564d5868,%eax
ffffffff821350b1: b9 27 00 00 00 mov $0x27,%ecx
ffffffff821350b6: 31 d2 xor %edx,%edx
ffffffff821350b8: bb 04 00 00 00 mov $0x4,%ebx
ffffffff821350bd: 66 ba 58 56 mov $0x5658,%dx
ffffffff821350c1: ed in (%dx),%eax <-- hypercall
ffffffff821350c2: 89 1f mov %ebx,(%rdi) <-- crash
The full disassembly shows that RDI should contain the value of a valid
kernel stack address (0xff5eeb3240003e54). Instead it contains
0x40003e54, suggesting the hypervisor cleared the upper 32 bits.
This issue was bisected to commit aca282ab7e75 ("x86/asm: Annotate
special section entries"), which added annotations to the ALTERNATIVE()
macro. Despite the use of asm_inline, that commit caused the compiler
to un-inline and const-propagate vmware_hypercall4().
That made RDI live across the hypercall, making the hypervisor's
register clobbering visible and exposing this latent bug. Technically
the bug is in QEMU, but we still need to support old "broken" versions.
This is also exacerbated by CONFIG_DEBUG_SECTION_MISMATCH which sets
-fno-inline-functions-called-once, causing once-called functions to be
not inlined, and in this case const-propagated as well.
In theory this same issue exists for all the hypercalls in the vmmouse
driver; in practice it has only been seen with vmware_hypercall3() and
vmware_hypercall4(). For now, just mark RDI/RSI as clobbered for those
two calls. This should have a minimal effect on code generation overall
as it should be rare for the compiler to want to make RDI/RSI live
across hypercalls.
Fixes: 34bf25e820ae ("x86/vmware: Introduce VMware hypercall API")
Fixes: aca282ab7e75 ("x86/asm: Annotate special section entries")
Reported-by: Justin Forbes <jforbes@fedoraproject.org>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
arch/x86/include/asm/vmware.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h
index c9cf43d5ef23..4220dae14a2d 100644
--- a/arch/x86/include/asm/vmware.h
+++ b/arch/x86/include/asm/vmware.h
@@ -140,7 +140,7 @@ unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1,
"b" (in1),
"c" (cmd),
"d" (0)
- : "cc", "memory");
+ : "di", "si", "cc", "memory");
return out0;
}
@@ -165,7 +165,7 @@ unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1,
"b" (in1),
"c" (cmd),
"d" (0)
- : "cc", "memory");
+ : "di", "si", "cc", "memory");
return out0;
}
--
2.52.0
On Fri, 6 Feb 2026 at 14:25, Josh Poimboeuf <jpoimboe@kernel.org> wrote:
>
> Here ya go:
I'm going to change that commit message to make it clear that it's a
QEMU bug, plain and simple. There's no point in claiming this fixes a
kernel bug when it's a pure workaround for a bug elsewhere.
Linus
On Fri, 6 Feb 2026 at 14:38, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> I'm going to change that commit message to make it clear that it's a
> QEMU bug, plain and simple. There's no point in claiming this fixes a
> kernel bug when it's a pure workaround for a bug elsewhere.
I have created an issue at gitlab:
https://gitlab.com/qemu-project/qemu/-/issues/3293
and hopefully this will get fixed in QEMU at some point.
Adding Paolo to the participants, since he presumably knows what to do
with qemu, since he touched that qemu file a couple of months ago.
(The fix looks trivial, as suggested by Alexey: just change the
"uint32_t data[6];" to use target_ulong instead of uint32_t, but
somebody needs to test it and maybe qemu has other rules for register
types)
Linus
On Fri, Feb 06, 2026 at 03:08:29PM -0800, Linus Torvalds wrote: > On Fri, 6 Feb 2026 at 14:38, Linus Torvalds > <torvalds@linux-foundation.org> wrote: > > > > I'm going to change that commit message to make it clear that it's a > > QEMU bug, plain and simple. There's no point in claiming this fixes a > > kernel bug when it's a pure workaround for a bug elsewhere. > > I have created an issue at gitlab: > > https://gitlab.com/qemu-project/qemu/-/issues/3293 > > and hopefully this will get fixed in QEMU at some point. > > Adding Paolo to the participants, since he presumably knows what to do > with qemu, since he touched that qemu file a couple of months ago. > > (The fix looks trivial, as suggested by Alexey: just change the > "uint32_t data[6];" to use target_ulong instead of uint32_t, but > somebody needs to test it and maybe qemu has other rules for register > types) I posted a QEMU fix here: https://lists.gnu.org/archive/html/qemu-devel/2026-02/msg01713.html (using uint64_t instead of target_ulong at the maintainer's request as they are phasing out the target_ulong type). -- Josh
On Fri, 6 Feb 2026 at 16:46, Josh Poimboeuf <jpoimboe@kernel.org> wrote:
>
> (using uint64_t instead of target_ulong at the maintainer's request as
> they are phasing out the target_ulong type).
Ahh. I'm reading emails in the wrong order, this answers the question
I had about the 32-bit host case..
Linus
On Thu, Jan 22, 2026 at 02:00:50AM -0800, Alexey Makhalov wrote: > Hi Josh, > > Thanks for reporting the problem. > > VMware hypercall 0x27 (VMWARE_CMD_ABSPOINTER_DATA) handler only modifies > (returns data) on the first 4 arguments, regs: RAX, RBX, RCX, RDX. > It does not and should not clobber any other guest registers except CC > state. > > From the Oops message, the hardware is QEMU Standard PC. > And the issue is caused by the vmmouse emulation there, specifically in > vmmouse_ioport_read() function. > > 1. vmmouse_get_data(data) saves lower 32 bit for all 6 args. > https://github.com/qemu/qemu/blob/master/hw/i386/vmmouse.c#L227 > 2. vmmouse_data() processes the hypercall preparing the data for the first 4 > arguments. https://github.com/qemu/qemu/blob/master/hw/i386/vmmouse.c#L255 > 3. vmmouse_set_data(data). Copies only lower 32 bit back to all 6 args and > _zeroes_ upper 32 bits for untouched RDI and RSI. > > Workarounding QEMU misbehavior from the kernel side by introducing less > efficient asm inlines does not sound correct. > > Please report or fix the issue from QEMU side. > Recommended QEMU fix: vmmouse_get_data/vmmouse_set_data should save/restore > target_ulong type instead of uint32_t. Ah, not sure how I didn't see that was QEMU. I will report/fix it there. Thanks! -- Josh
© 2016 - 2026 Red Hat, Inc.