efi/x86: Remove GDT setup from efi_main
The 64-bit kernel will already load a GDT in startup_64, which is the next function to execute after return from efi_main. Add GDT setup code to the 32-bit kernel's startup_32 as well. Doing it in the head code has the advantage that we can avoid potentially corrupting the GDT during copy/decompression. This also removes dependence on having a specific GDT layout setup by the bootloader. Both startup_32 and startup_64 now clear interrupts on entry, so we can remove that from efi_main as well. Signed-off-by: Arvind Sankar <nivedita@alum.mit.edu> Link: https://lore.kernel.org/r/20200202171353.3736319-6-nivedita@alum.mit.edu Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
This commit is contained in:
parent
cae0e431a0
commit
ef5a7b5eb1
@ -712,10 +712,8 @@ struct boot_params *efi_main(efi_handle_t handle,
|
||||
efi_system_table_t *sys_table_arg,
|
||||
struct boot_params *boot_params)
|
||||
{
|
||||
struct desc_ptr *gdt = NULL;
|
||||
struct setup_header *hdr = &boot_params->hdr;
|
||||
efi_status_t status;
|
||||
struct desc_struct *desc;
|
||||
unsigned long cmdline_paddr;
|
||||
|
||||
sys_table = sys_table_arg;
|
||||
@ -753,20 +751,6 @@ struct boot_params *efi_main(efi_handle_t handle,
|
||||
|
||||
setup_quirks(boot_params);
|
||||
|
||||
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, sizeof(*gdt),
|
||||
(void **)&gdt);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_printk("Failed to allocate memory for 'gdt' structure\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
gdt->size = 0x800;
|
||||
status = efi_low_alloc(gdt->size, 8, (unsigned long *)&gdt->address);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_printk("Failed to allocate memory for 'gdt'\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the kernel isn't already loaded at the preferred load
|
||||
* address, relocate it.
|
||||
@ -793,93 +777,6 @@ struct boot_params *efi_main(efi_handle_t handle,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
memset((char *)gdt->address, 0x0, gdt->size);
|
||||
desc = (struct desc_struct *)gdt->address;
|
||||
|
||||
/* The first GDT is a dummy. */
|
||||
desc++;
|
||||
|
||||
if (IS_ENABLED(CONFIG_X86_64)) {
|
||||
/* __KERNEL32_CS */
|
||||
desc->limit0 = 0xffff;
|
||||
desc->base0 = 0x0000;
|
||||
desc->base1 = 0x0000;
|
||||
desc->type = SEG_TYPE_CODE | SEG_TYPE_EXEC_READ;
|
||||
desc->s = DESC_TYPE_CODE_DATA;
|
||||
desc->dpl = 0;
|
||||
desc->p = 1;
|
||||
desc->limit1 = 0xf;
|
||||
desc->avl = 0;
|
||||
desc->l = 0;
|
||||
desc->d = SEG_OP_SIZE_32BIT;
|
||||
desc->g = SEG_GRANULARITY_4KB;
|
||||
desc->base2 = 0x00;
|
||||
|
||||
desc++;
|
||||
} else {
|
||||
/* Second entry is unused on 32-bit */
|
||||
desc++;
|
||||
}
|
||||
|
||||
/* __KERNEL_CS */
|
||||
desc->limit0 = 0xffff;
|
||||
desc->base0 = 0x0000;
|
||||
desc->base1 = 0x0000;
|
||||
desc->type = SEG_TYPE_CODE | SEG_TYPE_EXEC_READ;
|
||||
desc->s = DESC_TYPE_CODE_DATA;
|
||||
desc->dpl = 0;
|
||||
desc->p = 1;
|
||||
desc->limit1 = 0xf;
|
||||
desc->avl = 0;
|
||||
|
||||
if (IS_ENABLED(CONFIG_X86_64)) {
|
||||
desc->l = 1;
|
||||
desc->d = 0;
|
||||
} else {
|
||||
desc->l = 0;
|
||||
desc->d = SEG_OP_SIZE_32BIT;
|
||||
}
|
||||
desc->g = SEG_GRANULARITY_4KB;
|
||||
desc->base2 = 0x00;
|
||||
desc++;
|
||||
|
||||
/* __KERNEL_DS */
|
||||
desc->limit0 = 0xffff;
|
||||
desc->base0 = 0x0000;
|
||||
desc->base1 = 0x0000;
|
||||
desc->type = SEG_TYPE_DATA | SEG_TYPE_READ_WRITE;
|
||||
desc->s = DESC_TYPE_CODE_DATA;
|
||||
desc->dpl = 0;
|
||||
desc->p = 1;
|
||||
desc->limit1 = 0xf;
|
||||
desc->avl = 0;
|
||||
desc->l = 0;
|
||||
desc->d = SEG_OP_SIZE_32BIT;
|
||||
desc->g = SEG_GRANULARITY_4KB;
|
||||
desc->base2 = 0x00;
|
||||
desc++;
|
||||
|
||||
if (IS_ENABLED(CONFIG_X86_64)) {
|
||||
/* Task segment value */
|
||||
desc->limit0 = 0x0000;
|
||||
desc->base0 = 0x0000;
|
||||
desc->base1 = 0x0000;
|
||||
desc->type = SEG_TYPE_TSS;
|
||||
desc->s = 0;
|
||||
desc->dpl = 0;
|
||||
desc->p = 1;
|
||||
desc->limit1 = 0x0;
|
||||
desc->avl = 0;
|
||||
desc->l = 0;
|
||||
desc->d = 0;
|
||||
desc->g = SEG_GRANULARITY_4KB;
|
||||
desc->base2 = 0x00;
|
||||
desc++;
|
||||
}
|
||||
|
||||
asm volatile("cli");
|
||||
asm volatile ("lgdt %0" : : "m" (*gdt));
|
||||
|
||||
return boot_params;
|
||||
fail:
|
||||
efi_printk("efi_main() failed!\n");
|
||||
|
@ -64,12 +64,6 @@
|
||||
SYM_FUNC_START(startup_32)
|
||||
cld
|
||||
cli
|
||||
movl $__BOOT_DS, %eax
|
||||
movl %eax, %ds
|
||||
movl %eax, %es
|
||||
movl %eax, %fs
|
||||
movl %eax, %gs
|
||||
movl %eax, %ss
|
||||
|
||||
/*
|
||||
* Calculate the delta between where we were compiled to run
|
||||
@ -84,6 +78,19 @@ SYM_FUNC_START(startup_32)
|
||||
1: popl %ebp
|
||||
subl $1b, %ebp
|
||||
|
||||
/* Load new GDT */
|
||||
leal gdt(%ebp), %eax
|
||||
movl %eax, 2(%eax)
|
||||
lgdt (%eax)
|
||||
|
||||
/* Load segment registers with our descriptors */
|
||||
movl $__BOOT_DS, %eax
|
||||
movl %eax, %ds
|
||||
movl %eax, %es
|
||||
movl %eax, %fs
|
||||
movl %eax, %gs
|
||||
movl %eax, %ss
|
||||
|
||||
/*
|
||||
* %ebp contains the address we are loaded at by the boot loader and %ebx
|
||||
* contains the address where we should move the kernel image temporarily
|
||||
@ -129,6 +136,16 @@ SYM_FUNC_START(startup_32)
|
||||
cld
|
||||
popl %esi
|
||||
|
||||
/*
|
||||
* The GDT may get overwritten either during the copy we just did or
|
||||
* during extract_kernel below. To avoid any issues, repoint the GDTR
|
||||
* to the new copy of the GDT. EAX still contains the previously
|
||||
* calculated relocation offset of init_size - _end.
|
||||
*/
|
||||
leal gdt(%ebx), %edx
|
||||
addl %eax, 2(%edx)
|
||||
lgdt (%edx)
|
||||
|
||||
/*
|
||||
* Jump to the relocated address.
|
||||
*/
|
||||
@ -201,6 +218,17 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
|
||||
jmp *%eax
|
||||
SYM_FUNC_END(.Lrelocated)
|
||||
|
||||
.data
|
||||
.balign 8
|
||||
SYM_DATA_START_LOCAL(gdt)
|
||||
.word gdt_end - gdt - 1
|
||||
.long 0
|
||||
.word 0
|
||||
.quad 0x0000000000000000 /* Reserved */
|
||||
.quad 0x00cf9a000000ffff /* __KERNEL_CS */
|
||||
.quad 0x00cf92000000ffff /* __KERNEL_DS */
|
||||
SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt_end)
|
||||
|
||||
/*
|
||||
* Stack and heap for uncompression
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user