Commit 64e68263 authored by Joerg Roedel's avatar Joerg Roedel Committed by Borislav Petkov

x86/boot/compressed/64: Add IDT Infrastructure

Add code needed to setup an IDT in the early pre-decompression
boot-code. The IDT is loaded first in startup_64, which is after
EfiExitBootServices() has been called, and later reloaded when the
kernel image has been relocated to the end of the decompression area.

This allows to setup different IDT handlers before and after the
relocation.
Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20200907131613.12703-14-joro@8bytes.org
parent 6ba0efa4
...@@ -85,6 +85,7 @@ vmlinux-objs-$(CONFIG_EARLY_PRINTK) += $(obj)/early_serial_console.o ...@@ -85,6 +85,7 @@ vmlinux-objs-$(CONFIG_EARLY_PRINTK) += $(obj)/early_serial_console.o
vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += $(obj)/kaslr.o vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += $(obj)/kaslr.o
ifdef CONFIG_X86_64 ifdef CONFIG_X86_64
vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += $(obj)/kaslr_64.o vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += $(obj)/kaslr_64.o
vmlinux-objs-y += $(obj)/idt_64.o $(obj)/idt_handlers_64.o
vmlinux-objs-y += $(obj)/mem_encrypt.o vmlinux-objs-y += $(obj)/mem_encrypt.o
vmlinux-objs-y += $(obj)/pgtable_64.o vmlinux-objs-y += $(obj)/pgtable_64.o
endif endif
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <asm/processor-flags.h> #include <asm/processor-flags.h>
#include <asm/asm-offsets.h> #include <asm/asm-offsets.h>
#include <asm/bootparam.h> #include <asm/bootparam.h>
#include <asm/desc_defs.h>
#include "pgtable.h" #include "pgtable.h"
/* /*
...@@ -410,6 +411,10 @@ SYM_CODE_START(startup_64) ...@@ -410,6 +411,10 @@ SYM_CODE_START(startup_64)
.Lon_kernel_cs: .Lon_kernel_cs:
pushq %rsi
call load_stage1_idt
popq %rsi
/* /*
* paging_prepare() sets up the trampoline and checks if we need to * paging_prepare() sets up the trampoline and checks if we need to
* enable 5-level paging. * enable 5-level paging.
...@@ -537,6 +542,13 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated) ...@@ -537,6 +542,13 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
shrq $3, %rcx shrq $3, %rcx
rep stosq rep stosq
/*
* Load stage2 IDT
*/
pushq %rsi
call load_stage2_idt
popq %rsi
/* /*
* Do the extraction, and jump to the new kernel.. * Do the extraction, and jump to the new kernel..
*/ */
...@@ -690,10 +702,21 @@ SYM_DATA_START_LOCAL(gdt) ...@@ -690,10 +702,21 @@ SYM_DATA_START_LOCAL(gdt)
.quad 0x0000000000000000 /* TS continued */ .quad 0x0000000000000000 /* TS continued */
SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt_end) SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt_end)
SYM_DATA_START(boot_idt_desc)
.word boot_idt_end - boot_idt - 1
.quad 0
SYM_DATA_END(boot_idt_desc)
.balign 8
SYM_DATA_START(boot_idt)
.rept BOOT_IDT_ENTRIES
.quad 0
.quad 0
.endr
SYM_DATA_END_LABEL(boot_idt, SYM_L_GLOBAL, boot_idt_end)
#ifdef CONFIG_EFI_STUB #ifdef CONFIG_EFI_STUB
SYM_DATA(image_offset, .long 0) SYM_DATA(image_offset, .long 0)
#endif #endif
#ifdef CONFIG_EFI_MIXED #ifdef CONFIG_EFI_MIXED
SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0) SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0)
SYM_DATA(efi_is64, .byte 1) SYM_DATA(efi_is64, .byte 1)
......
// SPDX-License-Identifier: GPL-2.0-only
#include <asm/trap_pf.h>
#include <asm/segment.h>
#include <asm/trapnr.h>
#include "misc.h"
static void set_idt_entry(int vector, void (*handler)(void))
{
unsigned long address = (unsigned long)handler;
gate_desc entry;
memset(&entry, 0, sizeof(entry));
entry.offset_low = (u16)(address & 0xffff);
entry.segment = __KERNEL_CS;
entry.bits.type = GATE_TRAP;
entry.bits.p = 1;
entry.offset_middle = (u16)((address >> 16) & 0xffff);
entry.offset_high = (u32)(address >> 32);
memcpy(&boot_idt[vector], &entry, sizeof(entry));
}
/* Have this here so we don't need to include <asm/desc.h> */
static void load_boot_idt(const struct desc_ptr *dtr)
{
asm volatile("lidt %0"::"m" (*dtr));
}
/* Setup IDT before kernel jumping to .Lrelocated */
void load_stage1_idt(void)
{
boot_idt_desc.address = (unsigned long)boot_idt;
load_boot_idt(&boot_idt_desc);
}
/* Setup IDT after kernel jumping to .Lrelocated */
void load_stage2_idt(void)
{
boot_idt_desc.address = (unsigned long)boot_idt;
load_boot_idt(&boot_idt_desc);
}
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Early IDT handler entry points
*
* Copyright (C) 2019 SUSE
*
* Author: Joerg Roedel <jroedel@suse.de>
*/
#include <asm/segment.h>
/* For ORIG_RAX */
#include "../../entry/calling.h"
.macro EXCEPTION_HANDLER name function error_code=0
SYM_FUNC_START(\name)
/* Build pt_regs */
.if \error_code == 0
pushq $0
.endif
pushq %rdi
pushq %rsi
pushq %rdx
pushq %rcx
pushq %rax
pushq %r8
pushq %r9
pushq %r10
pushq %r11
pushq %rbx
pushq %rbp
pushq %r12
pushq %r13
pushq %r14
pushq %r15
/* Call handler with pt_regs */
movq %rsp, %rdi
/* Error code is second parameter */
movq ORIG_RAX(%rsp), %rsi
call \function
/* Restore regs */
popq %r15
popq %r14
popq %r13
popq %r12
popq %rbp
popq %rbx
popq %r11
popq %r10
popq %r9
popq %r8
popq %rax
popq %rcx
popq %rdx
popq %rsi
popq %rdi
/* Remove error code and return */
addq $8, %rsp
iretq
SYM_FUNC_END(\name)
.endm
.text
.code64
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <asm/page.h> #include <asm/page.h>
#include <asm/boot.h> #include <asm/boot.h>
#include <asm/bootparam.h> #include <asm/bootparam.h>
#include <asm/desc_defs.h>
#define BOOT_CTYPE_H #define BOOT_CTYPE_H
#include <linux/acpi.h> #include <linux/acpi.h>
...@@ -133,4 +134,8 @@ int count_immovable_mem_regions(void); ...@@ -133,4 +134,8 @@ int count_immovable_mem_regions(void);
static inline int count_immovable_mem_regions(void) { return 0; } static inline int count_immovable_mem_regions(void) { return 0; }
#endif #endif
/* idt_64.c */
extern gate_desc boot_idt[BOOT_IDT_ENTRIES];
extern struct desc_ptr boot_idt_desc;
#endif /* BOOT_COMPRESSED_MISC_H */ #endif /* BOOT_COMPRESSED_MISC_H */
...@@ -109,6 +109,9 @@ struct desc_ptr { ...@@ -109,6 +109,9 @@ struct desc_ptr {
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */
/* Boot IDT definitions */
#define BOOT_IDT_ENTRIES 32
/* Access rights as returned by LAR */ /* Access rights as returned by LAR */
#define AR_TYPE_RODATA (0 * (1 << 9)) #define AR_TYPE_RODATA (0 * (1 << 9))
#define AR_TYPE_RWDATA (1 * (1 << 9)) #define AR_TYPE_RWDATA (1 * (1 << 9))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment