You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
82 lines
1.9 KiB
C
82 lines
1.9 KiB
C
/* Copyright (C) 2021,2022 fef <owo@fef.moe>. All rights reserved. */
|
|
|
|
#include <arch/page.h>
|
|
#include <arch/trap.h>
|
|
|
|
#include <gay/cdefs.h>
|
|
#include <gay/kprintf.h>
|
|
#include <gay/systm.h>
|
|
#include <gay/types.h>
|
|
|
|
/*
|
|
* Initial Page Directory Pointer Table and Page Map Level 4 Table for the
|
|
* assembly startup routine (see setup64.S). Used for statically mapping the
|
|
* lowest 2 GB of physical memory into the -2 GB virtual area.
|
|
*/
|
|
__asmlink x86_pdpt_t _pdpt0;
|
|
__asmlink x86_pml4t_t _pml4t;
|
|
|
|
void x86_isr_page_fault(trap_frame_t *frame, u32 error_code)
|
|
{
|
|
void *address;
|
|
__asm__ volatile(
|
|
" mov %%cr2, %0 \n"
|
|
: "=r"(address)
|
|
:
|
|
);
|
|
|
|
const char *space;
|
|
if (error_code & X86_PF_USER)
|
|
space = "user";
|
|
else
|
|
space = "kernel";
|
|
|
|
const char *rwx;
|
|
if (error_code & X86_PF_WRITE)
|
|
rwx = "write to";
|
|
else if (error_code & X86_PF_INSTR)
|
|
rwx = "exec at";
|
|
else
|
|
rwx = "read from";
|
|
|
|
const char *present;
|
|
if (error_code & X86_PF_PRESENT)
|
|
present = "";
|
|
else
|
|
present = " non-mapped";
|
|
|
|
kprintf("\n########## B O N K ##########\n");
|
|
kprintf("Illegal %s %s%s address %p!\n", space, rwx, present, address);
|
|
print_regs(frame);
|
|
panic("Page fault");
|
|
}
|
|
|
|
vm_paddr_t vtophys(void *virt)
|
|
{
|
|
x86_pml4te_t *pml4te = X86_PML4TE(virt);
|
|
if (!pml4te->flags.present)
|
|
return (vm_paddr_t)-1;
|
|
|
|
x86_pdpte_t *pdpte = X86_PDPTE(virt);
|
|
if (!pdpte->flags.present)
|
|
return (vm_paddr_t)-1;
|
|
if (pdpte->flags.huge) {
|
|
vm_paddr_t phys_base = pdpte->val & X86_PMAP_MASK;
|
|
return phys_base + ((vm_paddr_t)virt % (1 << X86_PDPT_SHIFT));
|
|
}
|
|
|
|
x86_pdte_t *pdte = X86_PDTE(virt);
|
|
if (!pdte->flags.present)
|
|
return (vm_paddr_t)-1;
|
|
if (pdte->flags.huge) {
|
|
vm_paddr_t phys_base = pdte->val & X86_PMAP_MASK;
|
|
return phys_base + ((vm_paddr_t)virt % (1 << X86_PDT_SHIFT));
|
|
}
|
|
|
|
x86_pte_t *pte = X86_PTE(virt);
|
|
if (!pte->flags.present)
|
|
return (vm_paddr_t)-1;
|
|
vm_paddr_t phys_base = pte->val & X86_PMAP_MASK;
|
|
return phys_base + ((vm_paddr_t)virt % (1 << X86_PT_SHIFT));
|
|
}
|