qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] target/i386: svm: fix sign extension of exit code
@ 2025-11-15  0:26 Paolo Bonzini
  2025-11-17  9:42 ` Richard Henderson
  0 siblings, 1 reply; 6+ messages in thread
From: Paolo Bonzini @ 2025-11-15  0:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable

The exit_code parameter of cpu_vmexit is declared as uint32_t, but exit
codes are 64 bits wide according to the AMD SVM specification.  And because
uint32_t is unsigned, this causes exit codes to be zero-extended, for example
writing SVM_EXIT_ERR as 0xffff_ffff instead of the expected 0xffff_ffff_ffff_ffff.

Cc: qemu-stable@nongnu.org
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2977
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target/i386/tcg/helper-tcg.h        | 2 +-
 target/i386/tcg/system/svm_helper.c | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/target/i386/tcg/helper-tcg.h b/target/i386/tcg/helper-tcg.h
index be011b06b7c..e41cbda407a 100644
--- a/target/i386/tcg/helper-tcg.h
+++ b/target/i386/tcg/helper-tcg.h
@@ -99,7 +99,7 @@ void cpu_load_eflags(CPUX86State *env, int eflags, int update_mask);
 
 /* system/svm_helper.c */
 #ifndef CONFIG_USER_ONLY
-G_NORETURN void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code,
+G_NORETURN void cpu_vmexit(CPUX86State *nenv, uint64_t exit_code,
                            uint64_t exit_info_1, uintptr_t retaddr);
 void do_vmexit(CPUX86State *env);
 #endif
diff --git a/target/i386/tcg/system/svm_helper.c b/target/i386/tcg/system/svm_helper.c
index 505788b0e26..4b86796518f 100644
--- a/target/i386/tcg/system/svm_helper.c
+++ b/target/i386/tcg/system/svm_helper.c
@@ -128,7 +128,7 @@ static inline bool virtual_gif_enabled(CPUX86State *env)
     return false;
 }
 
-static inline bool virtual_vm_load_save_enabled(CPUX86State *env, uint32_t exit_code, uintptr_t retaddr)
+static inline bool virtual_vm_load_save_enabled(CPUX86State *env, uint64_t exit_code, uintptr_t retaddr)
 {
     uint64_t lbr_ctl;
 
@@ -723,7 +723,7 @@ void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param,
     }
 }
 
-void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1,
+void cpu_vmexit(CPUX86State *env, uint64_t exit_code, uint64_t exit_info_1,
                 uintptr_t retaddr)
 {
     CPUState *cs = env_cpu(env);
@@ -732,7 +732,7 @@ void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1,
 
     qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016"
                   PRIx64 ", " TARGET_FMT_lx ")!\n",
-                  exit_code, exit_info_1,
+                  (uint32_t)exit_code, exit_info_1,
                   x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
                                                    control.exit_info_2)),
                   env->eip);
-- 
2.51.1



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] target/i386: svm: fix sign extension of exit code
  2025-11-15  0:26 [PATCH] target/i386: svm: fix sign extension of exit code Paolo Bonzini
@ 2025-11-17  9:42 ` Richard Henderson
  2025-11-17 11:32   ` Paolo Bonzini
  0 siblings, 1 reply; 6+ messages in thread
From: Richard Henderson @ 2025-11-17  9:42 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel; +Cc: qemu-stable

On 11/15/25 01:26, Paolo Bonzini wrote:
> -void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1,
> +void cpu_vmexit(CPUX86State *env, uint64_t exit_code, uint64_t exit_info_1,
>                   uintptr_t retaddr)
>   {
>       CPUState *cs = env_cpu(env);
> @@ -732,7 +732,7 @@ void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1,
>   
>       qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016"
>                     PRIx64 ", " TARGET_FMT_lx ")!\n",
> -                  exit_code, exit_info_1,
> +                  (uint32_t)exit_code, exit_info_1,

Why cast instead of printing all 64 bits?

Otherwise,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] target/i386: svm: fix sign extension of exit code
  2025-11-17  9:42 ` Richard Henderson
@ 2025-11-17 11:32   ` Paolo Bonzini
  2025-11-18  8:31     ` Richard Henderson
  0 siblings, 1 reply; 6+ messages in thread
From: Paolo Bonzini @ 2025-11-17 11:32 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: qemu-stable

On 11/17/25 10:42, Richard Henderson wrote:
> On 11/15/25 01:26, Paolo Bonzini wrote:
>> -void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t 
>> exit_info_1,
>> +void cpu_vmexit(CPUX86State *env, uint64_t exit_code, uint64_t 
>> exit_info_1,
>>                   uintptr_t retaddr)
>>   {
>>       CPUState *cs = env_cpu(env);
>> @@ -732,7 +732,7 @@ void cpu_vmexit(CPUX86State *env, uint32_t 
>> exit_code, uint64_t exit_info_1,
>>       qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", 
>> %016"
>>                     PRIx64 ", " TARGET_FMT_lx ")!\n",
>> -                  exit_code, exit_info_1,
>> +                  (uint32_t)exit_code, exit_info_1,
> 
> Why cast instead of printing all 64 bits?

Because in practice exit_code is either a very small negative value 
(-1...-4) or a positive value.  For QEMU in addition the positive value 
will also be small (less than 16 bits); values between 0x8000_0000 and 
0xffff_ffff could happen in principle but are for use by software and by 
the processor[1].  So the high 32 bits are basically unused, and the 
cast removes eight zeroes or f's from the log.

Paolo

[1] see for example arch/x86/include/uapi/asm/svm.h in Linux:

#define SVM_VMGEXIT_MMIO_READ                   0x80000001
#define SVM_VMGEXIT_MMIO_WRITE                  0x80000002
#define SVM_VMGEXIT_NMI_COMPLETE                0x80000003
#define SVM_VMGEXIT_AP_HLT_LOOP                 0x80000004
#define SVM_VMGEXIT_AP_JUMP_TABLE               0x80000005
#define SVM_VMGEXIT_PSC                         0x80000010
#define SVM_VMGEXIT_GUEST_REQUEST               0x80000011
#define SVM_VMGEXIT_EXT_GUEST_REQUEST           0x80000012
#define SVM_VMGEXIT_AP_CREATION                 0x80000013
#define SVM_VMGEXIT_SNP_RUN_VMPL                0x80000018
#define SVM_VMGEXIT_SAVIC                       0x8000001a
#define SVM_VMGEXIT_HV_FEATURES                 0x8000fffd
#define SVM_VMGEXIT_TERM_REQUEST                0x8000fffe
#define SVM_VMGEXIT_UNSUPPORTED_EVENT           0x8000ffff
#define SVM_EXIT_SW                             0xf0000000

SVM_VMGEXIT_* values are actually stored by the guest in its own memory, 
not by the processor; whereas SVM_EXIT_SW is only used in nested 
virtualization scenarios and will not be passed to cpu_vmexit.



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] target/i386: svm: fix sign extension of exit code
  2025-11-17 11:32   ` Paolo Bonzini
@ 2025-11-18  8:31     ` Richard Henderson
  2025-11-18 13:07       ` Paolo Bonzini
  0 siblings, 1 reply; 6+ messages in thread
From: Richard Henderson @ 2025-11-18  8:31 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel; +Cc: qemu-stable

On 11/17/25 12:32, Paolo Bonzini wrote:
> On 11/17/25 10:42, Richard Henderson wrote:
>> On 11/15/25 01:26, Paolo Bonzini wrote:
>>> -void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1,
>>> +void cpu_vmexit(CPUX86State *env, uint64_t exit_code, uint64_t exit_info_1,
>>>                   uintptr_t retaddr)
>>>   {
>>>       CPUState *cs = env_cpu(env);
>>> @@ -732,7 +732,7 @@ void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t 
>>> exit_info_1,
>>>       qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016"
>>>                     PRIx64 ", " TARGET_FMT_lx ")!\n",
>>> -                  exit_code, exit_info_1,
>>> +                  (uint32_t)exit_code, exit_info_1,
>>
>> Why cast instead of printing all 64 bits?
> 
> Because in practice exit_code is either a very small negative value (-1...-4) or a 
> positive value.  For QEMU in addition the positive value will also be small (less than 16 
> bits); values between 0x8000_0000 and 0xffff_ffff could happen in principle but are for 
> use by software and by the processor[1].  So the high 32 bits are basically unused, and 
> the cast removes eight zeroes or f's from the log.

Then maybe you really want the signed int64_t?


r~


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] target/i386: svm: fix sign extension of exit code
  2025-11-18  8:31     ` Richard Henderson
@ 2025-11-18 13:07       ` Paolo Bonzini
  2025-11-19 10:59         ` Richard Henderson
  0 siblings, 1 reply; 6+ messages in thread
From: Paolo Bonzini @ 2025-11-18 13:07 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, qemu-stable

On Tue, Nov 18, 2025 at 9:31 AM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 11/17/25 12:32, Paolo Bonzini wrote:
> > On 11/17/25 10:42, Richard Henderson wrote:
> >> On 11/15/25 01:26, Paolo Bonzini wrote:
> >>> -void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1,
> >>> +void cpu_vmexit(CPUX86State *env, uint64_t exit_code, uint64_t exit_info_1,
> >>>                   uintptr_t retaddr)
> >>>   {
> >>>       CPUState *cs = env_cpu(env);
> >>> @@ -732,7 +732,7 @@ void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t
> >>> exit_info_1,
> >>>       qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016"
> >>>                     PRIx64 ", " TARGET_FMT_lx ")!\n",
> >>> -                  exit_code, exit_info_1,
> >>> +                  (uint32_t)exit_code, exit_info_1,
> >>
> >> Why cast instead of printing all 64 bits?
> >
> > Because in practice exit_code is either a very small negative value (-1...-4) or a
> > positive value.  For QEMU in addition the positive value will also be small (less than 16
> > bits); values between 0x8000_0000 and 0xffff_ffff could happen in principle but are for
> > use by software and by the processor[1].  So the high 32 bits are basically unused, and
> > the cast removes eight zeroes or f's from the log.
>
> Then maybe you really want the signed int64_t?

The problem is not in the type (int64_t or uint64_t work equally well,
they're all just constants), it's in the format string. Positive codes
are written in hexadecimal in the manual, so:
- %ld makes it hard to match the positive codes in the manual
- %lx still prints a -1 as ffffffffffffffff.

So all the cast is doing is making the log more readable.

Paolo



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] target/i386: svm: fix sign extension of exit code
  2025-11-18 13:07       ` Paolo Bonzini
@ 2025-11-19 10:59         ` Richard Henderson
  0 siblings, 0 replies; 6+ messages in thread
From: Richard Henderson @ 2025-11-19 10:59 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel, qemu-stable

On 11/18/25 14:07, Paolo Bonzini wrote:
> On Tue, Nov 18, 2025 at 9:31 AM Richard Henderson
> <richard.henderson@linaro.org> wrote:
>>
>> On 11/17/25 12:32, Paolo Bonzini wrote:
>>> On 11/17/25 10:42, Richard Henderson wrote:
>>>> On 11/15/25 01:26, Paolo Bonzini wrote:
>>>>> -void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1,
>>>>> +void cpu_vmexit(CPUX86State *env, uint64_t exit_code, uint64_t exit_info_1,
>>>>>                    uintptr_t retaddr)
>>>>>    {
>>>>>        CPUState *cs = env_cpu(env);
>>>>> @@ -732,7 +732,7 @@ void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t
>>>>> exit_info_1,
>>>>>        qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016"
>>>>>                      PRIx64 ", " TARGET_FMT_lx ")!\n",
>>>>> -                  exit_code, exit_info_1,
>>>>> +                  (uint32_t)exit_code, exit_info_1,
>>>>
>>>> Why cast instead of printing all 64 bits?
>>>
>>> Because in practice exit_code is either a very small negative value (-1...-4) or a
>>> positive value.  For QEMU in addition the positive value will also be small (less than 16
>>> bits); values between 0x8000_0000 and 0xffff_ffff could happen in principle but are for
>>> use by software and by the processor[1].  So the high 32 bits are basically unused, and
>>> the cast removes eight zeroes or f's from the log.
>>
>> Then maybe you really want the signed int64_t?
> 
> The problem is not in the type (int64_t or uint64_t work equally well,
> they're all just constants), it's in the format string. Positive codes
> are written in hexadecimal in the manual, so:
> - %ld makes it hard to match the positive codes in the manual
> - %lx still prints a -1 as ffffffffffffffff.
> 
> So all the cast is doing is making the log more readable.

Ok then.


r~


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-11-19 11:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-15  0:26 [PATCH] target/i386: svm: fix sign extension of exit code Paolo Bonzini
2025-11-17  9:42 ` Richard Henderson
2025-11-17 11:32   ` Paolo Bonzini
2025-11-18  8:31     ` Richard Henderson
2025-11-18 13:07       ` Paolo Bonzini
2025-11-19 10:59         ` Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).