qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH] target/i386: Truncate ESP when exiting from long mode
@ 2023-07-26  8:17 Ard Biesheuvel
  2023-07-26 15:01 ` Richard Henderson
  0 siblings, 1 reply; 7+ messages in thread
From: Ard Biesheuvel @ 2023-07-26  8:17 UTC (permalink / raw)
  To: qemu-devel
  Cc: Ard Biesheuvel, Paolo Bonzini, Richard Henderson, Eduardo Habkost

While working on some EFI boot changes for Linux/x86, I noticed that TCG
deviates from bare metal when it comes to how it handles the value of
the stack pointer register RSP when dropping out of long mode.

On bare metal, RSP is truncated to 32 bits, even if the code that runs
in 32-bit protected mode never uses the stack at all (and uses a long
jump rather than long return to switch back to long mode). This means
64-bit code cannot rely on RSP surviving any excursions into 32-bit
protected mode (with paging disabled).

Let's align TCG with this behavior, so that code that relies on RSP
retaining its value does not inadvertently work while bare metal does
not.

Observed on Intel Ice Lake cores.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <richard.henderson@linaro.org>
Cc: Eduardo Habkost <eduardo@habkost.net>
Link: https://lore.kernel.org/all/20230711091453.2543622-11-ardb@kernel.org/
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
I used this patch locally to reproduce an issue that was reported on Ice
Lake but didn't trigger in my QEMU testing.

Hints welcome on where the architectural behavior is specified, and in
particular, whether or not other 64-bit GPRs can be relied upon to
preserve their full 64-bit length values.

 target/i386/helper.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/i386/helper.c b/target/i386/helper.c
index 89aa696c6d53d68c..a338da23a87746ed 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -149,6 +149,7 @@ void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
         env->efer &= ~MSR_EFER_LMA;
         env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
         env->eip &= 0xffffffff;
+        env->regs[R_ESP] &= 0xffffffff;
     }
 #endif
     env->cr[0] = new_cr0 | CR0_ET_MASK;
-- 
2.39.2



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

* Re: [RFC PATCH] target/i386: Truncate ESP when exiting from long mode
  2023-07-26  8:17 [RFC PATCH] target/i386: Truncate ESP when exiting from long mode Ard Biesheuvel
@ 2023-07-26 15:01 ` Richard Henderson
  2023-07-27 17:56   ` Richard Henderson
  2023-07-31  8:35   ` Ard Biesheuvel
  0 siblings, 2 replies; 7+ messages in thread
From: Richard Henderson @ 2023-07-26 15:01 UTC (permalink / raw)
  To: Ard Biesheuvel, qemu-devel; +Cc: Paolo Bonzini, Eduardo Habkost

On 7/26/23 01:17, Ard Biesheuvel wrote:
> While working on some EFI boot changes for Linux/x86, I noticed that TCG deviates from
> bare metal when it comes to how it handles the value of the stack pointer register RSP
> when dropping out of long mode.
> 
> On bare metal, RSP is truncated to 32 bits, even if the code that runs in 32-bit
> protected mode never uses the stack at all (and uses a long jump rather than long
> return to switch back to long mode). This means 64-bit code cannot rely on RSP
> surviving any excursions into 32-bit protected mode (with paging disabled).
> 
> Let's align TCG with this behavior, so that code that relies on RSP retaining its value
> does not inadvertently work while bare metal does not.
> 
> Observed on Intel Ice Lake cores.
> 
> Cc: Paolo Bonzini<pbonzini@redhat.com> Cc: Richard
> Henderson<richard.henderson@linaro.org> Cc: Eduardo Habkost<eduardo@habkost.net> 
> Link:https://lore.kernel.org/all/20230711091453.2543622-11-ardb@kernel.org/ 
> Signed-off-by: Ard Biesheuvel<ardb@kernel.org> --- I used this patch locally to
> reproduce an issue that was reported on Ice Lake but didn't trigger in my QEMU
> testing.
> 
> Hints welcome on where the architectural behavior is specified, and in particular,
> whether or not other 64-bit GPRs can be relied upon to preserve their full 64-bit
> length values.

No idea about chapter and verse, but it has the feel of being part and parcel with the
truncation of eip.  While esp is always special, I suspect that none of the GPRs can be 
relied on carrying all bits.

I'm happy with the change though, since similar behaviour can be observed on hw.

Acked-by: Richard Henderson <richard.henderson@linaro.org>


r~


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

* Re: [RFC PATCH] target/i386: Truncate ESP when exiting from long mode
  2023-07-26 15:01 ` Richard Henderson
@ 2023-07-27 17:56   ` Richard Henderson
  2023-07-27 21:36     ` Ard Biesheuvel
  2023-07-31  8:35   ` Ard Biesheuvel
  1 sibling, 1 reply; 7+ messages in thread
From: Richard Henderson @ 2023-07-27 17:56 UTC (permalink / raw)
  To: Ard Biesheuvel, qemu-devel; +Cc: Paolo Bonzini, Eduardo Habkost

On 7/26/23 08:01, Richard Henderson wrote:
> On 7/26/23 01:17, Ard Biesheuvel wrote:
>> Hints welcome on where the architectural behavior is specified, and in particular,
>> whether or not other 64-bit GPRs can be relied upon to preserve their full 64-bit
>> length values.
> 
> No idea about chapter and verse, but it has the feel of being part and parcel with the
> truncation of eip.  While esp is always special, I suspect that none of the GPRs can be 
> relied on carrying all bits.

Coincidentally, I was having a gander at the newly announced APX extension [1],
and happened across

3.1.4.1.2 Extended GPR Access (Direct and Indirect)

     ... Entering/leaving 64-bit mode via traditional (explicit)
     control flow does not directly alter the content of the EGPRs
     (EGPRs behave similar to R8-R15 in this regard).

which suggests to me that the 8 low registers are squashed to 32-bit
on transition to 32-bit IA-32e mode.

I still have not found similar language in the main architecture manual.


r~


[1] 
https://www.intel.com/content/www/us/en/content-details/784266/intel-advanced-performance-extensions-intel-apx-architecture-specification.html



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

* Re: [RFC PATCH] target/i386: Truncate ESP when exiting from long mode
  2023-07-27 17:56   ` Richard Henderson
@ 2023-07-27 21:36     ` Ard Biesheuvel
  2023-07-28  0:17       ` Richard Henderson
  0 siblings, 1 reply; 7+ messages in thread
From: Ard Biesheuvel @ 2023-07-27 21:36 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, Paolo Bonzini, Eduardo Habkost

On Thu, 27 Jul 2023 at 19:56, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 7/26/23 08:01, Richard Henderson wrote:
> > On 7/26/23 01:17, Ard Biesheuvel wrote:
> >> Hints welcome on where the architectural behavior is specified, and in particular,
> >> whether or not other 64-bit GPRs can be relied upon to preserve their full 64-bit
> >> length values.
> >
> > No idea about chapter and verse, but it has the feel of being part and parcel with the
> > truncation of eip.  While esp is always special, I suspect that none of the GPRs can be
> > relied on carrying all bits.
>
> Coincidentally, I was having a gander at the newly announced APX extension [1],
> and happened across
>
> 3.1.4.1.2 Extended GPR Access (Direct and Indirect)
>
>      ... Entering/leaving 64-bit mode via traditional (explicit)
>      control flow does not directly alter the content of the EGPRs
>      (EGPRs behave similar to R8-R15 in this regard).
>
> which suggests to me that the 8 low registers are squashed to 32-bit
> on transition to 32-bit IA-32e mode.
>
> I still have not found similar language in the main architecture manual.
>

Interesting - that matches my observations on those Ice Lake cores:
RSP will be truncated, but preserving/restoring it to/from R8 across
the exit from long mode works fine.


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

* Re: [RFC PATCH] target/i386: Truncate ESP when exiting from long mode
  2023-07-27 21:36     ` Ard Biesheuvel
@ 2023-07-28  0:17       ` Richard Henderson
  2023-07-28 16:47         ` Ard Biesheuvel
  0 siblings, 1 reply; 7+ messages in thread
From: Richard Henderson @ 2023-07-28  0:17 UTC (permalink / raw)
  To: Ard Biesheuvel; +Cc: qemu-devel, Paolo Bonzini, Eduardo Habkost

On 7/27/23 14:36, Ard Biesheuvel wrote:
> On Thu, 27 Jul 2023 at 19:56, Richard Henderson
> <richard.henderson@linaro.org> wrote:
>>
>> On 7/26/23 08:01, Richard Henderson wrote:
>>> On 7/26/23 01:17, Ard Biesheuvel wrote:
>>>> Hints welcome on where the architectural behavior is specified, and in particular,
>>>> whether or not other 64-bit GPRs can be relied upon to preserve their full 64-bit
>>>> length values.
>>>
>>> No idea about chapter and verse, but it has the feel of being part and parcel with the
>>> truncation of eip.  While esp is always special, I suspect that none of the GPRs can be
>>> relied on carrying all bits.
>>
>> Coincidentally, I was having a gander at the newly announced APX extension [1],
>> and happened across
>>
>> 3.1.4.1.2 Extended GPR Access (Direct and Indirect)
>>
>>       ... Entering/leaving 64-bit mode via traditional (explicit)
>>       control flow does not directly alter the content of the EGPRs
>>       (EGPRs behave similar to R8-R15 in this regard).
>>
>> which suggests to me that the 8 low registers are squashed to 32-bit
>> on transition to 32-bit IA-32e mode.
>>
>> I still have not found similar language in the main architecture manual.
>>
> 
> Interesting - that matches my observations on those Ice Lake cores:
> RSP will be truncated, but preserving/restoring it to/from R8 across
> the exit from long mode works fine.

Found it:

Volume 1 Basic Architecture
3.4.1.1 General-Purpose Registers in 64-Bit Mode

# Registers only available in 64-bit mode (R8-R15 and XMM8-XMM15)
# are preserved across transitions from 64-bit mode into compatibility mode
# then back into 64-bit mode. However, values of R8-R15 and XMM8-XMM15 are
# undefined after transitions from 64-bit mode through compatibility mode
# to legacy or real mode and then back through compatibility mode to 64-bit mode.


r~


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

* Re: [RFC PATCH] target/i386: Truncate ESP when exiting from long mode
  2023-07-28  0:17       ` Richard Henderson
@ 2023-07-28 16:47         ` Ard Biesheuvel
  0 siblings, 0 replies; 7+ messages in thread
From: Ard Biesheuvel @ 2023-07-28 16:47 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, Paolo Bonzini, Eduardo Habkost

On Fri, 28 Jul 2023 at 02:17, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 7/27/23 14:36, Ard Biesheuvel wrote:
> > On Thu, 27 Jul 2023 at 19:56, Richard Henderson
> > <richard.henderson@linaro.org> wrote:
> >>
> >> On 7/26/23 08:01, Richard Henderson wrote:
> >>> On 7/26/23 01:17, Ard Biesheuvel wrote:
> >>>> Hints welcome on where the architectural behavior is specified, and in particular,
> >>>> whether or not other 64-bit GPRs can be relied upon to preserve their full 64-bit
> >>>> length values.
> >>>
> >>> No idea about chapter and verse, but it has the feel of being part and parcel with the
> >>> truncation of eip.  While esp is always special, I suspect that none of the GPRs can be
> >>> relied on carrying all bits.
> >>
> >> Coincidentally, I was having a gander at the newly announced APX extension [1],
> >> and happened across
> >>
> >> 3.1.4.1.2 Extended GPR Access (Direct and Indirect)
> >>
> >>       ... Entering/leaving 64-bit mode via traditional (explicit)
> >>       control flow does not directly alter the content of the EGPRs
> >>       (EGPRs behave similar to R8-R15 in this regard).
> >>
> >> which suggests to me that the 8 low registers are squashed to 32-bit
> >> on transition to 32-bit IA-32e mode.
> >>
> >> I still have not found similar language in the main architecture manual.
> >>
> >
> > Interesting - that matches my observations on those Ice Lake cores:
> > RSP will be truncated, but preserving/restoring it to/from R8 across
> > the exit from long mode works fine.
>
> Found it:
>
> Volume 1 Basic Architecture
> 3.4.1.1 General-Purpose Registers in 64-Bit Mode
>
> # Registers only available in 64-bit mode (R8-R15 and XMM8-XMM15)
> # are preserved across transitions from 64-bit mode into compatibility mode
> # then back into 64-bit mode. However, values of R8-R15 and XMM8-XMM15 are
> # undefined after transitions from 64-bit mode through compatibility mode
> # to legacy or real mode and then back through compatibility mode to 64-bit mode.
>

Thanks. Not what I was hoping though ...


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

* Re: [RFC PATCH] target/i386: Truncate ESP when exiting from long mode
  2023-07-26 15:01 ` Richard Henderson
  2023-07-27 17:56   ` Richard Henderson
@ 2023-07-31  8:35   ` Ard Biesheuvel
  1 sibling, 0 replies; 7+ messages in thread
From: Ard Biesheuvel @ 2023-07-31  8:35 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, Paolo Bonzini, Eduardo Habkost

On Wed, 26 Jul 2023 at 17:01, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 7/26/23 01:17, Ard Biesheuvel wrote:
> > While working on some EFI boot changes for Linux/x86, I noticed that TCG deviates from
> > bare metal when it comes to how it handles the value of the stack pointer register RSP
> > when dropping out of long mode.
> >
> > On bare metal, RSP is truncated to 32 bits, even if the code that runs in 32-bit
> > protected mode never uses the stack at all (and uses a long jump rather than long
> > return to switch back to long mode). This means 64-bit code cannot rely on RSP
> > surviving any excursions into 32-bit protected mode (with paging disabled).
> >
> > Let's align TCG with this behavior, so that code that relies on RSP retaining its value
> > does not inadvertently work while bare metal does not.
> >
> > Observed on Intel Ice Lake cores.
> >
> > Cc: Paolo Bonzini<pbonzini@redhat.com> Cc: Richard
> > Henderson<richard.henderson@linaro.org> Cc: Eduardo Habkost<eduardo@habkost.net>
> > Link:https://lore.kernel.org/all/20230711091453.2543622-11-ardb@kernel.org/
> > Signed-off-by: Ard Biesheuvel<ardb@kernel.org> --- I used this patch locally to
> > reproduce an issue that was reported on Ice Lake but didn't trigger in my QEMU
> > testing.
> >
> > Hints welcome on where the architectural behavior is specified, and in particular,
> > whether or not other 64-bit GPRs can be relied upon to preserve their full 64-bit
> > length values.
>
> No idea about chapter and verse, but it has the feel of being part and parcel with the
> truncation of eip.  While esp is always special, I suspect that none of the GPRs can be
> relied on carrying all bits.
>
> I'm happy with the change though, since similar behaviour can be observed on hw.
>
> Acked-by: Richard Henderson <richard.henderson@linaro.org>
>

I experimented with truncating all GPRs that exist in 32-bit mode, and
this actually breaks kexec on Linux if it happens to load the kernel
above 4G (which it appears to do reproducibly when sufficient memory
is available)

This is due to the 4/5 level paging switch trampoline, which is called
while RBX, RBP and RSI are live and refer to assets in memory that may
reside above 4G.

I am fixing that code, but it does mean we should probably limit this
change to ESP (as apparently, current hw only happens to truncate ESP
but no other GPRs)


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

end of thread, other threads:[~2023-07-31  8:36 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-07-26  8:17 [RFC PATCH] target/i386: Truncate ESP when exiting from long mode Ard Biesheuvel
2023-07-26 15:01 ` Richard Henderson
2023-07-27 17:56   ` Richard Henderson
2023-07-27 21:36     ` Ard Biesheuvel
2023-07-28  0:17       ` Richard Henderson
2023-07-28 16:47         ` Ard Biesheuvel
2023-07-31  8:35   ` Ard Biesheuvel

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).