x86/boot/compressed/64: Add page-fault handler
Install a page-fault handler to add an identity mapping to addresses not yet mapped. Also do some checking whether the error code is sane. This makes non SEV-ES machines use the exception handling infrastructure in the pre-decompressions boot code too, making it less likely to break in the future. Signed-off-by: Joerg Roedel <jroedel@suse.de> Signed-off-by: Borislav Petkov <bp@suse.de> Reviewed-by: Kees Cook <keescook@chromium.org> Link: https://lkml.kernel.org/r/20200907131613.12703-16-joro@8bytes.org
This commit is contained in:
parent
5f2bb01682
commit
8b0d3b3b41
@ -19,10 +19,13 @@
|
||||
/* No PAGE_TABLE_ISOLATION support needed either: */
|
||||
#undef CONFIG_PAGE_TABLE_ISOLATION
|
||||
|
||||
#include "error.h"
|
||||
#include "misc.h"
|
||||
|
||||
/* These actually do the work of building the kernel identity maps. */
|
||||
#include <linux/pgtable.h>
|
||||
#include <asm/trap_pf.h>
|
||||
#include <asm/trapnr.h>
|
||||
#include <asm/init.h>
|
||||
/* Use the static base for this part of the boot process */
|
||||
#undef __PAGE_OFFSET
|
||||
@ -160,3 +163,39 @@ void finalize_identity_maps(void)
|
||||
{
|
||||
write_cr3(top_level_pgt);
|
||||
}
|
||||
|
||||
static void do_pf_error(const char *msg, unsigned long error_code,
|
||||
unsigned long address, unsigned long ip)
|
||||
{
|
||||
error_putstr(msg);
|
||||
|
||||
error_putstr("\nError Code: ");
|
||||
error_puthex(error_code);
|
||||
error_putstr("\nCR2: 0x");
|
||||
error_puthex(address);
|
||||
error_putstr("\nRIP relative to _head: 0x");
|
||||
error_puthex(ip - (unsigned long)_head);
|
||||
error_putstr("\n");
|
||||
|
||||
error("Stopping.\n");
|
||||
}
|
||||
|
||||
void do_boot_page_fault(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
unsigned long address = native_read_cr2();
|
||||
|
||||
/*
|
||||
* Check for unexpected error codes. Unexpected are:
|
||||
* - Faults on present pages
|
||||
* - User faults
|
||||
* - Reserved bits set
|
||||
*/
|
||||
if (error_code & (X86_PF_PROT | X86_PF_USER | X86_PF_RSVD))
|
||||
do_pf_error("Unexpected page-fault:", error_code, address, regs->ip);
|
||||
|
||||
/*
|
||||
* Error code is sane - now identity map the 2M region around
|
||||
* the faulting address.
|
||||
*/
|
||||
add_identity_map(address & PMD_MASK, PMD_SIZE);
|
||||
}
|
||||
|
@ -40,5 +40,7 @@ void load_stage2_idt(void)
|
||||
{
|
||||
boot_idt_desc.address = (unsigned long)boot_idt;
|
||||
|
||||
set_idt_entry(X86_TRAP_PF, boot_page_fault);
|
||||
|
||||
load_boot_idt(&boot_idt_desc);
|
||||
}
|
||||
|
@ -68,3 +68,5 @@ SYM_FUNC_END(\name)
|
||||
|
||||
.text
|
||||
.code64
|
||||
|
||||
EXCEPTION_HANDLER boot_page_fault do_boot_page_fault error_code=1
|
||||
|
@ -37,6 +37,9 @@
|
||||
#define memptr unsigned
|
||||
#endif
|
||||
|
||||
/* boot/compressed/vmlinux start and end markers */
|
||||
extern char _head[], _end[];
|
||||
|
||||
/* misc.c */
|
||||
extern memptr free_mem_ptr;
|
||||
extern memptr free_mem_end_ptr;
|
||||
@ -146,4 +149,7 @@ extern pteval_t __default_kernel_pte_mask;
|
||||
extern gate_desc boot_idt[BOOT_IDT_ENTRIES];
|
||||
extern struct desc_ptr boot_idt_desc;
|
||||
|
||||
/* IDT Entry Points */
|
||||
void boot_page_fault(void);
|
||||
|
||||
#endif /* BOOT_COMPRESSED_MISC_H */
|
||||
|
Loading…
Reference in New Issue
Block a user