Skip to content

Commit

Permalink
x86/boot/compressed/64: Add page-fault handler
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Borislav Petkov <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
  • Loading branch information
joergroedel authored and suryasaimadhu committed Sep 7, 2020
1 parent 5f2bb01 commit 8b0d3b3
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 0 deletions.
39 changes: 39 additions & 0 deletions arch/x86/boot/compressed/ident_map_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
2 changes: 2 additions & 0 deletions arch/x86/boot/compressed/idt_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
2 changes: 2 additions & 0 deletions arch/x86/boot/compressed/idt_handlers_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,5 @@ SYM_FUNC_END(\name)

.text
.code64

EXCEPTION_HANDLER boot_page_fault do_boot_page_fault error_code=1
6 changes: 6 additions & 0 deletions arch/x86/boot/compressed/misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 */

0 comments on commit 8b0d3b3

Please sign in to comment.