x86/head/64: Move early exception dispatch to C code
Move the assembly coded dispatch between page-faults and all other exceptions to C code to make it easier to maintain and extend. Also change the return-type of early_make_pgtable() to bool and make it static. Signed-off-by: Joerg Roedel <jroedel@suse.de> Signed-off-by: Borislav Petkov <bp@suse.de> Link: https://lkml.kernel.org/r/20200907131613.12703-36-joro@8bytes.org
This commit is contained in:
Родитель
097ee5b778
Коммит
4b47cdbda6
|
@ -28,7 +28,7 @@
|
||||||
#include <asm-generic/pgtable_uffd.h>
|
#include <asm-generic/pgtable_uffd.h>
|
||||||
|
|
||||||
extern pgd_t early_top_pgt[PTRS_PER_PGD];
|
extern pgd_t early_top_pgt[PTRS_PER_PGD];
|
||||||
int __init __early_make_pgtable(unsigned long address, pmdval_t pmd);
|
bool __init __early_make_pgtable(unsigned long address, pmdval_t pmd);
|
||||||
|
|
||||||
void ptdump_walk_pgd_level(struct seq_file *m, struct mm_struct *mm);
|
void ptdump_walk_pgd_level(struct seq_file *m, struct mm_struct *mm);
|
||||||
void ptdump_walk_pgd_level_debugfs(struct seq_file *m, struct mm_struct *mm,
|
void ptdump_walk_pgd_level_debugfs(struct seq_file *m, struct mm_struct *mm,
|
||||||
|
|
|
@ -39,6 +39,8 @@ void vsmp_init(void);
|
||||||
static inline void vsmp_init(void) { }
|
static inline void vsmp_init(void) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct pt_regs;
|
||||||
|
|
||||||
void setup_bios_corruption_check(void);
|
void setup_bios_corruption_check(void);
|
||||||
void early_platform_quirks(void);
|
void early_platform_quirks(void);
|
||||||
|
|
||||||
|
@ -49,8 +51,8 @@ extern void i386_reserve_resources(void);
|
||||||
extern unsigned long __startup_64(unsigned long physaddr, struct boot_params *bp);
|
extern unsigned long __startup_64(unsigned long physaddr, struct boot_params *bp);
|
||||||
extern unsigned long __startup_secondary_64(void);
|
extern unsigned long __startup_secondary_64(void);
|
||||||
extern void startup_64_setup_env(unsigned long physbase);
|
extern void startup_64_setup_env(unsigned long physbase);
|
||||||
extern int early_make_pgtable(unsigned long address);
|
|
||||||
extern void early_setup_idt(void);
|
extern void early_setup_idt(void);
|
||||||
|
extern void __init do_early_exception(struct pt_regs *regs, int trapnr);
|
||||||
|
|
||||||
#ifdef CONFIG_X86_INTEL_MID
|
#ifdef CONFIG_X86_INTEL_MID
|
||||||
extern void x86_intel_mid_early_setup(void);
|
extern void x86_intel_mid_early_setup(void);
|
||||||
|
|
|
@ -38,6 +38,8 @@
|
||||||
#include <asm/fixmap.h>
|
#include <asm/fixmap.h>
|
||||||
#include <asm/realmode.h>
|
#include <asm/realmode.h>
|
||||||
#include <asm/desc.h>
|
#include <asm/desc.h>
|
||||||
|
#include <asm/extable.h>
|
||||||
|
#include <asm/trapnr.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Manage page tables very early on.
|
* Manage page tables very early on.
|
||||||
|
@ -317,7 +319,7 @@ static void __init reset_early_page_tables(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a new PMD entry */
|
/* Create a new PMD entry */
|
||||||
int __init __early_make_pgtable(unsigned long address, pmdval_t pmd)
|
bool __init __early_make_pgtable(unsigned long address, pmdval_t pmd)
|
||||||
{
|
{
|
||||||
unsigned long physaddr = address - __PAGE_OFFSET;
|
unsigned long physaddr = address - __PAGE_OFFSET;
|
||||||
pgdval_t pgd, *pgd_p;
|
pgdval_t pgd, *pgd_p;
|
||||||
|
@ -327,7 +329,7 @@ int __init __early_make_pgtable(unsigned long address, pmdval_t pmd)
|
||||||
|
|
||||||
/* Invalid address or early pgt is done ? */
|
/* Invalid address or early pgt is done ? */
|
||||||
if (physaddr >= MAXMEM || read_cr3_pa() != __pa_nodebug(early_top_pgt))
|
if (physaddr >= MAXMEM || read_cr3_pa() != __pa_nodebug(early_top_pgt))
|
||||||
return -1;
|
return false;
|
||||||
|
|
||||||
again:
|
again:
|
||||||
pgd_p = &early_top_pgt[pgd_index(address)].pgd;
|
pgd_p = &early_top_pgt[pgd_index(address)].pgd;
|
||||||
|
@ -384,10 +386,10 @@ again:
|
||||||
}
|
}
|
||||||
pmd_p[pmd_index(address)] = pmd;
|
pmd_p[pmd_index(address)] = pmd;
|
||||||
|
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __init early_make_pgtable(unsigned long address)
|
static bool __init early_make_pgtable(unsigned long address)
|
||||||
{
|
{
|
||||||
unsigned long physaddr = address - __PAGE_OFFSET;
|
unsigned long physaddr = address - __PAGE_OFFSET;
|
||||||
pmdval_t pmd;
|
pmdval_t pmd;
|
||||||
|
@ -397,6 +399,15 @@ int __init early_make_pgtable(unsigned long address)
|
||||||
return __early_make_pgtable(address, pmd);
|
return __early_make_pgtable(address, pmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __init do_early_exception(struct pt_regs *regs, int trapnr)
|
||||||
|
{
|
||||||
|
if (trapnr == X86_TRAP_PF &&
|
||||||
|
early_make_pgtable(native_read_cr2()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
early_fixup_exception(regs, trapnr);
|
||||||
|
}
|
||||||
|
|
||||||
/* Don't add a printk in there. printk relies on the PDA which is not initialized
|
/* Don't add a printk in there. printk relies on the PDA which is not initialized
|
||||||
yet. */
|
yet. */
|
||||||
static void __init clear_bss(void)
|
static void __init clear_bss(void)
|
||||||
|
|
|
@ -341,18 +341,9 @@ SYM_CODE_START_LOCAL(early_idt_handler_common)
|
||||||
pushq %r15 /* pt_regs->r15 */
|
pushq %r15 /* pt_regs->r15 */
|
||||||
UNWIND_HINT_REGS
|
UNWIND_HINT_REGS
|
||||||
|
|
||||||
cmpq $14,%rsi /* Page fault? */
|
|
||||||
jnz 10f
|
|
||||||
GET_CR2_INTO(%rdi) /* can clobber %rax if pv */
|
|
||||||
call early_make_pgtable
|
|
||||||
andl %eax,%eax
|
|
||||||
jz 20f /* All good */
|
|
||||||
|
|
||||||
10:
|
|
||||||
movq %rsp,%rdi /* RDI = pt_regs; RSI is already trapnr */
|
movq %rsp,%rdi /* RDI = pt_regs; RSI is already trapnr */
|
||||||
call early_fixup_exception
|
call do_early_exception
|
||||||
|
|
||||||
20:
|
|
||||||
decl early_recursion_flag(%rip)
|
decl early_recursion_flag(%rip)
|
||||||
jmp restore_regs_and_return_to_kernel
|
jmp restore_regs_and_return_to_kernel
|
||||||
SYM_CODE_END(early_idt_handler_common)
|
SYM_CODE_END(early_idt_handler_common)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче