Message ID | 20220412173407.13637-7-varad.gautam@suse.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | SMP Support for x86 UEFI Tests | expand |
On Tue, Apr 12, 2022, Varad Gautam wrote: > UEFI tests do not update MSR_GS_BASE during bringup, and continue > using the GS_BASE set up by the UEFI implementation for percpu > storage. > > Update this MSR during setup_segments64() to allow storing percpu > data at a sane location reserved by the testcase, and ensure that > this happens before any operation that ends up storing to the percpu > space It's worth noting in the changelog that reset_apic() needs to be moved below setup_gdt_tss() as it depends on per-cpu setup. That definitely won't be obvious to most people. > Signed-off-by: Varad Gautam <varad.gautam@suse.com> > --- > lib/x86/setup.c | 9 ++++++--- > x86/efi/efistart64.S | 7 +++++++ > 2 files changed, 13 insertions(+), 3 deletions(-) > > diff --git a/lib/x86/setup.c b/lib/x86/setup.c > index 7dd6677..5d32d3f 100644 > --- a/lib/x86/setup.c > +++ b/lib/x86/setup.c > @@ -170,7 +170,8 @@ void setup_multiboot(struct mbi_bootinfo *bi) > #ifdef CONFIG_EFI > > /* From x86/efi/efistart64.S */ > -extern void setup_segments64(void); > +extern void setup_segments64(u64 gs_base); > +extern u8 stacktop; > > static efi_status_t setup_memory_allocator(efi_bootinfo_t *efi_bootinfo) > { > @@ -271,12 +272,14 @@ static void setup_page_table(void) > static void setup_gdt_tss(void) > { > size_t tss_offset; > + u64 gs_base; > > /* 64-bit setup_tss does not use the stacktop argument. */ > tss_offset = setup_tss(NULL); > load_gdt_tss(tss_offset); > > - setup_segments64(); > + gs_base = (u64)(&stacktop) - (PAGE_SIZE * (pre_boot_apic_id() + 1)); Rather than follow the (IMO awful) non-EFI behavior of hijacking a chunk of the stack, which is a symptom of doing everything in asm, since this is now C we can declare a proper percpu array and index that. Disclaimer, this has only been tested with smp=1 at this point, haven't reached the end of the series :-) diff --git a/lib/x86/setup.c b/lib/x86/setup.c index 6131ea2..91a06f7 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -169,6 +169,8 @@ void setup_multiboot(struct mbi_bootinfo *bi) #ifdef CONFIG_EFI +static struct percpu_data __percpu_data[MAX_TEST_CPUS]; + static efi_status_t setup_memory_allocator(efi_bootinfo_t *efi_bootinfo) { int i; @@ -285,6 +287,8 @@ static void setup_gdt_tss(void) "1:" :: "r" ((u64)KERNEL_DS), "i" (KERNEL_CS) ); + + wrmsr(MSR_GS_BASE, (u64)&__percpu_data[pre_boot_apic_id()]); } efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo) @@ -326,8 +330,8 @@ efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo) return status; } - reset_apic(); setup_gdt_tss(); + reset_apic(); setup_idt(); load_idt(); mask_pic_interrupts();
diff --git a/lib/x86/setup.c b/lib/x86/setup.c index 7dd6677..5d32d3f 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -170,7 +170,8 @@ void setup_multiboot(struct mbi_bootinfo *bi) #ifdef CONFIG_EFI /* From x86/efi/efistart64.S */ -extern void setup_segments64(void); +extern void setup_segments64(u64 gs_base); +extern u8 stacktop; static efi_status_t setup_memory_allocator(efi_bootinfo_t *efi_bootinfo) { @@ -271,12 +272,14 @@ static void setup_page_table(void) static void setup_gdt_tss(void) { size_t tss_offset; + u64 gs_base; /* 64-bit setup_tss does not use the stacktop argument. */ tss_offset = setup_tss(NULL); load_gdt_tss(tss_offset); - setup_segments64(); + gs_base = (u64)(&stacktop) - (PAGE_SIZE * (pre_boot_apic_id() + 1)); + setup_segments64(gs_base); } efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo) @@ -318,8 +321,8 @@ efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo) return status; } - reset_apic(); setup_gdt_tss(); + reset_apic(); setup_idt(); load_idt(); mask_pic_interrupts(); diff --git a/x86/efi/efistart64.S b/x86/efi/efistart64.S index cb08230..1c38355 100644 --- a/x86/efi/efistart64.S +++ b/x86/efi/efistart64.S @@ -44,6 +44,13 @@ setup_segments64: mov %ax, %gs mov %ax, %ss + /* Setup percpu base */ + MSR_GS_BASE = 0xc0000101 + mov %rdi, %rax + mov $0, %edx + mov $MSR_GS_BASE, %ecx + wrmsr + /* * Update the code segment by putting it on the stack before the return * address, then doing a far return: this will use the new code segment
UEFI tests do not update MSR_GS_BASE during bringup, and continue using the GS_BASE set up by the UEFI implementation for percpu storage. Update this MSR during setup_segments64() to allow storing percpu data at a sane location reserved by the testcase, and ensure that this happens before any operation that ends up storing to the percpu space. Signed-off-by: Varad Gautam <varad.gautam@suse.com> --- lib/x86/setup.c | 9 ++++++--- x86/efi/efistart64.S | 7 +++++++ 2 files changed, 13 insertions(+), 3 deletions(-)