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