2024-04-24 16:21:34

by Ard Biesheuvel

[permalink] [raw]
Subject: [RFC PATCH 4/9] x86/purgatory: Avoid absolute reference to GDT

From: Ard Biesheuvel <[email protected]>

The purgatory is almost entirely position independent, without any need
for any relocation processing at load time except for the reference to
the GDT in the entry code. Generate this reference at runtime instead,
to remove the last R_X86_64_64 relocation from this code.

While the GDT itself needs to be preserved in memory as long as it is
live, the GDT descriptor that is used to program the GDT can be
discarded so it can be allocated on the stack.

Signed-off-by: Ard Biesheuvel <[email protected]>
---
arch/x86/purgatory/entry64.S | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/x86/purgatory/entry64.S b/arch/x86/purgatory/entry64.S
index 9913877b0dbe..888661d9db9c 100644
--- a/arch/x86/purgatory/entry64.S
+++ b/arch/x86/purgatory/entry64.S
@@ -16,7 +16,11 @@

SYM_CODE_START(entry64)
/* Setup a gdt that should be preserved */
- lgdt gdt(%rip)
+ leaq gdt(%rip), %rax
+ pushq %rax
+ pushw $gdt_end - gdt - 1
+ lgdt (%rsp)
+ addq $10, %rsp

/* load the data segments */
movl $0x18, %eax /* data segment */
@@ -83,8 +87,8 @@ SYM_DATA_START_LOCAL(gdt)
* 0x08 unused
* so use them as gdt ptr
*/
- .word gdt_end - gdt - 1
- .quad gdt
+ .word 0
+ .quad 0
.word 0, 0, 0

/* 0x10 4GB flat code segment */
--
2.44.0.769.g3c40516874-goog



2024-04-24 17:39:21

by Brian Gerst

[permalink] [raw]
Subject: Re: [RFC PATCH 4/9] x86/purgatory: Avoid absolute reference to GDT

On Wed, Apr 24, 2024 at 12:06 PM Ard Biesheuvel <[email protected]> wrote:
>
> From: Ard Biesheuvel <[email protected]>
>
> The purgatory is almost entirely position independent, without any need
> for any relocation processing at load time except for the reference to
> the GDT in the entry code. Generate this reference at runtime instead,
> to remove the last R_X86_64_64 relocation from this code.
>
> While the GDT itself needs to be preserved in memory as long as it is
> live, the GDT descriptor that is used to program the GDT can be
> discarded so it can be allocated on the stack.
>
> Signed-off-by: Ard Biesheuvel <[email protected]>
> ---
> arch/x86/purgatory/entry64.S | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/arch/x86/purgatory/entry64.S b/arch/x86/purgatory/entry64.S
> index 9913877b0dbe..888661d9db9c 100644
> --- a/arch/x86/purgatory/entry64.S
> +++ b/arch/x86/purgatory/entry64.S
> @@ -16,7 +16,11 @@
>
> SYM_CODE_START(entry64)
> /* Setup a gdt that should be preserved */
> - lgdt gdt(%rip)
> + leaq gdt(%rip), %rax
> + pushq %rax
> + pushw $gdt_end - gdt - 1
> + lgdt (%rsp)
> + addq $10, %rsp

This misaligns the stack, pushing 16 bytes on the stack but only
removing 10 (decimal).

>
> /* load the data segments */
> movl $0x18, %eax /* data segment */
> @@ -83,8 +87,8 @@ SYM_DATA_START_LOCAL(gdt)
> * 0x08 unused
> * so use them as gdt ptr

obsolete comment

> */
> - .word gdt_end - gdt - 1
> - .quad gdt
> + .word 0
> + .quad 0
> .word 0, 0, 0

This can be condensed down to:
.quad 0, 0

>
> /* 0x10 4GB flat code segment */
> --
> 2.44.0.769.g3c40516874-goog

Brian Gerst

2024-04-24 17:54:09

by Ard Biesheuvel

[permalink] [raw]
Subject: Re: [RFC PATCH 4/9] x86/purgatory: Avoid absolute reference to GDT

Hi Brian,

Thanks for taking a look.

On Wed, 24 Apr 2024 at 19:39, Brian Gerst <[email protected]> wrote:
>
> On Wed, Apr 24, 2024 at 12:06 PM Ard Biesheuvel <[email protected]> wrote:
> >
> > From: Ard Biesheuvel <[email protected]>
> >
> > The purgatory is almost entirely position independent, without any need
> > for any relocation processing at load time except for the reference to
> > the GDT in the entry code. Generate this reference at runtime instead,
> > to remove the last R_X86_64_64 relocation from this code.
> >
> > While the GDT itself needs to be preserved in memory as long as it is
> > live, the GDT descriptor that is used to program the GDT can be
> > discarded so it can be allocated on the stack.
> >
> > Signed-off-by: Ard Biesheuvel <[email protected]>
> > ---
> > arch/x86/purgatory/entry64.S | 10 +++++++---
> > 1 file changed, 7 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/x86/purgatory/entry64.S b/arch/x86/purgatory/entry64.S
> > index 9913877b0dbe..888661d9db9c 100644
> > --- a/arch/x86/purgatory/entry64.S
> > +++ b/arch/x86/purgatory/entry64.S
> > @@ -16,7 +16,11 @@
> >
> > SYM_CODE_START(entry64)
> > /* Setup a gdt that should be preserved */
> > - lgdt gdt(%rip)
> > + leaq gdt(%rip), %rax
> > + pushq %rax
> > + pushw $gdt_end - gdt - 1
> > + lgdt (%rsp)
> > + addq $10, %rsp
>
> This misaligns the stack, pushing 16 bytes on the stack but only
> removing 10 (decimal).
>

pushw subtracts 2 from RSP and stores a word. So the total size stored
is 10 decimal not 16.

> >
> > /* load the data segments */
> > movl $0x18, %eax /* data segment */
> > @@ -83,8 +87,8 @@ SYM_DATA_START_LOCAL(gdt)
> > * 0x08 unused
> > * so use them as gdt ptr
>
> obsolete comment
>
> > */
> > - .word gdt_end - gdt - 1
> > - .quad gdt
> > + .word 0
> > + .quad 0
> > .word 0, 0, 0
>
> This can be condensed down to:
> .quad 0, 0
>

This code and the comment are removed in the next patch.

2024-04-24 19:01:04

by Brian Gerst

[permalink] [raw]
Subject: Re: [RFC PATCH 4/9] x86/purgatory: Avoid absolute reference to GDT

On Wed, Apr 24, 2024 at 1:53 PM Ard Biesheuvel <[email protected]> wrote:
>
> Hi Brian,
>
> Thanks for taking a look.
>
> On Wed, 24 Apr 2024 at 19:39, Brian Gerst <[email protected]> wrote:
> >
> > On Wed, Apr 24, 2024 at 12:06 PM Ard Biesheuvel <[email protected]> wrote:
> > >
> > > From: Ard Biesheuvel <[email protected]>
> > >
> > > The purgatory is almost entirely position independent, without any need
> > > for any relocation processing at load time except for the reference to
> > > the GDT in the entry code. Generate this reference at runtime instead,
> > > to remove the last R_X86_64_64 relocation from this code.
> > >
> > > While the GDT itself needs to be preserved in memory as long as it is
> > > live, the GDT descriptor that is used to program the GDT can be
> > > discarded so it can be allocated on the stack.
> > >
> > > Signed-off-by: Ard Biesheuvel <[email protected]>
> > > ---
> > > arch/x86/purgatory/entry64.S | 10 +++++++---
> > > 1 file changed, 7 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/arch/x86/purgatory/entry64.S b/arch/x86/purgatory/entry64.S
> > > index 9913877b0dbe..888661d9db9c 100644
> > > --- a/arch/x86/purgatory/entry64.S
> > > +++ b/arch/x86/purgatory/entry64.S
> > > @@ -16,7 +16,11 @@
> > >
> > > SYM_CODE_START(entry64)
> > > /* Setup a gdt that should be preserved */
> > > - lgdt gdt(%rip)
> > > + leaq gdt(%rip), %rax
> > > + pushq %rax
> > > + pushw $gdt_end - gdt - 1
> > > + lgdt (%rsp)
> > > + addq $10, %rsp
> >
> > This misaligns the stack, pushing 16 bytes on the stack but only
> > removing 10 (decimal).
> >
>
> pushw subtracts 2 from RSP and stores a word. So the total size stored
> is 10 decimal not 16.

I didn't notice the pushw, since I didn't think a 16-bit push was even
possible in 64-bit mode. Unexpected, but clever.


Brian Gerst