Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/amd64/efirt_machdep.c
Show First 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | |||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
#include <vm/vm_extern.h> | #include <vm/vm_extern.h> | ||||
#include <vm/vm_map.h> | #include <vm/vm_map.h> | ||||
#include <vm/vm_object.h> | #include <vm/vm_object.h> | ||||
#include <vm/vm_page.h> | #include <vm/vm_page.h> | ||||
#include <vm/vm_pager.h> | #include <vm/vm_pager.h> | ||||
static pml5_entry_t *efi_pml5; | |||||
static pml4_entry_t *efi_pml4; | static pml4_entry_t *efi_pml4; | ||||
static vm_object_t obj_1t1_pt; | static vm_object_t obj_1t1_pt; | ||||
static vm_page_t efi_pml4_page; | static vm_page_t efi_pmltop_page; | ||||
static vm_pindex_t efi_1t1_idx; | static vm_pindex_t efi_1t1_idx; | ||||
void | void | ||||
efi_destroy_1t1_map(void) | efi_destroy_1t1_map(void) | ||||
{ | { | ||||
vm_page_t m; | vm_page_t m; | ||||
if (obj_1t1_pt != NULL) { | if (obj_1t1_pt != NULL) { | ||||
VM_OBJECT_RLOCK(obj_1t1_pt); | VM_OBJECT_RLOCK(obj_1t1_pt); | ||||
TAILQ_FOREACH(m, &obj_1t1_pt->memq, listq) | TAILQ_FOREACH(m, &obj_1t1_pt->memq, listq) | ||||
m->ref_count = VPRC_OBJREF; | m->ref_count = VPRC_OBJREF; | ||||
vm_wire_sub(obj_1t1_pt->resident_page_count); | vm_wire_sub(obj_1t1_pt->resident_page_count); | ||||
VM_OBJECT_RUNLOCK(obj_1t1_pt); | VM_OBJECT_RUNLOCK(obj_1t1_pt); | ||||
vm_object_deallocate(obj_1t1_pt); | vm_object_deallocate(obj_1t1_pt); | ||||
} | } | ||||
obj_1t1_pt = NULL; | obj_1t1_pt = NULL; | ||||
efi_pml4 = NULL; | efi_pml4 = NULL; | ||||
efi_pml4_page = NULL; | efi_pml5 = NULL; | ||||
efi_pmltop_page = NULL; | |||||
} | } | ||||
/* | /* | ||||
* Map a physical address from EFI runtime space into KVA space. Returns 0 to | * Map a physical address from EFI runtime space into KVA space. Returns 0 to | ||||
* indicate a failed mapping so that the caller may handle error. | * indicate a failed mapping so that the caller may handle error. | ||||
*/ | */ | ||||
vm_offset_t | vm_offset_t | ||||
efi_phys_to_kva(vm_paddr_t paddr) | efi_phys_to_kva(vm_paddr_t paddr) | ||||
Show All 10 Lines | efi_1t1_page(void) | ||||
return (vm_page_grab(obj_1t1_pt, efi_1t1_idx++, VM_ALLOC_NOBUSY | | return (vm_page_grab(obj_1t1_pt, efi_1t1_idx++, VM_ALLOC_NOBUSY | | ||||
VM_ALLOC_WIRED | VM_ALLOC_ZERO)); | VM_ALLOC_WIRED | VM_ALLOC_ZERO)); | ||||
} | } | ||||
static pt_entry_t * | static pt_entry_t * | ||||
efi_1t1_pte(vm_offset_t va) | efi_1t1_pte(vm_offset_t va) | ||||
{ | { | ||||
pml5_entry_t *pml5e; | |||||
pml4_entry_t *pml4e; | pml4_entry_t *pml4e; | ||||
pdp_entry_t *pdpe; | pdp_entry_t *pdpe; | ||||
pd_entry_t *pde; | pd_entry_t *pde; | ||||
pt_entry_t *pte; | pt_entry_t *pte; | ||||
vm_page_t m; | vm_page_t m; | ||||
vm_pindex_t pml4_idx, pdp_idx, pd_idx; | vm_pindex_t pml5_idx, pml4_idx, pdp_idx, pd_idx; | ||||
vm_paddr_t mphys; | vm_paddr_t mphys; | ||||
pml4_idx = pmap_pml4e_index(va); | pml4_idx = pmap_pml4e_index(va); | ||||
if (la57) { | |||||
pml5_idx = pmap_pml5e_index(va); | |||||
pml5e = &efi_pml5[pml5_idx]; | |||||
if (*pml5e == 0) { | |||||
m = efi_1t1_page(); | |||||
mphys = VM_PAGE_TO_PHYS(m); | |||||
*pml5e = mphys | X86_PG_RW | X86_PG_V; | |||||
} else { | |||||
mphys = *pml5e & PG_FRAME; | |||||
} | |||||
pml4e = (pml4_entry_t *)PHYS_TO_DMAP(mphys); | |||||
pml4e = &pml4e[pml4_idx]; | |||||
} else { | |||||
pml4e = &efi_pml4[pml4_idx]; | pml4e = &efi_pml4[pml4_idx]; | ||||
} | |||||
if (*pml4e == 0) { | if (*pml4e == 0) { | ||||
m = efi_1t1_page(); | m = efi_1t1_page(); | ||||
mphys = VM_PAGE_TO_PHYS(m); | mphys = VM_PAGE_TO_PHYS(m); | ||||
*pml4e = mphys | X86_PG_RW | X86_PG_V; | *pml4e = mphys | X86_PG_RW | X86_PG_V; | ||||
} else { | } else { | ||||
mphys = *pml4e & ~PAGE_MASK; | mphys = *pml4e & PG_FRAME; | ||||
} | } | ||||
pdpe = (pdp_entry_t *)PHYS_TO_DMAP(mphys); | pdpe = (pdp_entry_t *)PHYS_TO_DMAP(mphys); | ||||
pdp_idx = pmap_pdpe_index(va); | pdp_idx = pmap_pdpe_index(va); | ||||
pdpe += pdp_idx; | pdpe += pdp_idx; | ||||
if (*pdpe == 0) { | if (*pdpe == 0) { | ||||
m = efi_1t1_page(); | m = efi_1t1_page(); | ||||
mphys = VM_PAGE_TO_PHYS(m); | mphys = VM_PAGE_TO_PHYS(m); | ||||
*pdpe = mphys | X86_PG_RW | X86_PG_V; | *pdpe = mphys | X86_PG_RW | X86_PG_V; | ||||
} else { | } else { | ||||
mphys = *pdpe & ~PAGE_MASK; | mphys = *pdpe & PG_FRAME; | ||||
} | } | ||||
pde = (pd_entry_t *)PHYS_TO_DMAP(mphys); | pde = (pd_entry_t *)PHYS_TO_DMAP(mphys); | ||||
pd_idx = pmap_pde_index(va); | pd_idx = pmap_pde_index(va); | ||||
pde += pd_idx; | pde += pd_idx; | ||||
if (*pde == 0) { | if (*pde == 0) { | ||||
m = efi_1t1_page(); | m = efi_1t1_page(); | ||||
mphys = VM_PAGE_TO_PHYS(m); | mphys = VM_PAGE_TO_PHYS(m); | ||||
*pde = mphys | X86_PG_RW | X86_PG_V; | *pde = mphys | X86_PG_RW | X86_PG_V; | ||||
} else { | } else { | ||||
mphys = *pde & ~PAGE_MASK; | mphys = *pde & PG_FRAME; | ||||
} | } | ||||
pte = (pt_entry_t *)PHYS_TO_DMAP(mphys); | pte = (pt_entry_t *)PHYS_TO_DMAP(mphys); | ||||
pte += pmap_pte_index(va); | pte += pmap_pte_index(va); | ||||
KASSERT(*pte == 0, ("va %#jx *pt %#jx", va, *pte)); | KASSERT(*pte == 0, ("va %#jx *pt %#jx", va, *pte)); | ||||
return (pte); | return (pte); | ||||
} | } | ||||
bool | bool | ||||
efi_create_1t1_map(struct efi_md *map, int ndesc, int descsz) | efi_create_1t1_map(struct efi_md *map, int ndesc, int descsz) | ||||
{ | { | ||||
struct efi_md *p; | struct efi_md *p; | ||||
pt_entry_t *pte; | pt_entry_t *pte; | ||||
void *pml; | |||||
vm_offset_t va; | vm_offset_t va; | ||||
uint64_t idx; | uint64_t idx; | ||||
int bits, i, mode; | int bits, i, mode; | ||||
obj_1t1_pt = vm_pager_allocate(OBJT_PHYS, NULL, ptoa(1 + | obj_1t1_pt = vm_pager_allocate(OBJT_PHYS, NULL, ptoa(1 + | ||||
NPML4EPG + NPML4EPG * NPDPEPG + NPML4EPG * NPDPEPG * NPDEPG), | NPML4EPG + NPML4EPG * NPDPEPG + NPML4EPG * NPDPEPG * NPDEPG), | ||||
VM_PROT_ALL, 0, NULL); | VM_PROT_ALL, 0, NULL); | ||||
efi_1t1_idx = 0; | efi_1t1_idx = 0; | ||||
VM_OBJECT_WLOCK(obj_1t1_pt); | VM_OBJECT_WLOCK(obj_1t1_pt); | ||||
efi_pml4_page = efi_1t1_page(); | efi_pmltop_page = efi_1t1_page(); | ||||
VM_OBJECT_WUNLOCK(obj_1t1_pt); | VM_OBJECT_WUNLOCK(obj_1t1_pt); | ||||
efi_pml4 = (pml4_entry_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(efi_pml4_page)); | pml = (void *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(efi_pmltop_page)); | ||||
pmap_pinit_pml4(efi_pml4_page); | if (la57) { | ||||
efi_pml5 = pml; | |||||
pmap_pinit_pml5(efi_pmltop_page); | |||||
} else { | |||||
efi_pml4 = pml; | |||||
pmap_pinit_pml4(efi_pmltop_page); | |||||
} | |||||
for (i = 0, p = map; i < ndesc; i++, p = efi_next_descriptor(p, | for (i = 0, p = map; i < ndesc; i++, p = efi_next_descriptor(p, | ||||
descsz)) { | descsz)) { | ||||
if ((p->md_attr & EFI_MD_ATTR_RT) == 0) | if ((p->md_attr & EFI_MD_ATTR_RT) == 0) | ||||
continue; | continue; | ||||
if (p->md_virt != NULL && (uint64_t)p->md_virt != p->md_phys) { | if (p->md_virt != NULL && (uint64_t)p->md_virt != p->md_phys) { | ||||
if (bootverbose) | if (bootverbose) | ||||
printf("EFI Runtime entry %d is mapped\n", i); | printf("EFI Runtime entry %d is mapped\n", i); | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | efi_arch_enter(void) | ||||
* %cr3 from the curpmap->pm_cr3, which would disable runtime | * %cr3 from the curpmap->pm_cr3, which would disable runtime | ||||
* segments mappings. Block the handler's action by setting | * segments mappings. Block the handler's action by setting | ||||
* curpmap to impossible value. See also comment in | * curpmap to impossible value. See also comment in | ||||
* pmap.c:pmap_activate_sw(). | * pmap.c:pmap_activate_sw(). | ||||
*/ | */ | ||||
if (pmap_pcid_enabled && !invpcid_works) | if (pmap_pcid_enabled && !invpcid_works) | ||||
PCPU_SET(curpmap, NULL); | PCPU_SET(curpmap, NULL); | ||||
load_cr3(VM_PAGE_TO_PHYS(efi_pml4_page) | (pmap_pcid_enabled ? | load_cr3(VM_PAGE_TO_PHYS(efi_pmltop_page) | (pmap_pcid_enabled ? | ||||
curpmap->pm_pcids[PCPU_GET(cpuid)].pm_pcid : 0)); | curpmap->pm_pcids[PCPU_GET(cpuid)].pm_pcid : 0)); | ||||
/* | /* | ||||
* If PCID is enabled, the clear CR3_PCID_SAVE bit in the loaded %cr3 | * If PCID is enabled, the clear CR3_PCID_SAVE bit in the loaded %cr3 | ||||
* causes TLB invalidation. | * causes TLB invalidation. | ||||
*/ | */ | ||||
if (!pmap_pcid_enabled) | if (!pmap_pcid_enabled) | ||||
invltlb(); | invltlb(); | ||||
return (0); | return (0); | ||||
▲ Show 20 Lines • Show All 41 Lines • Show Last 20 Lines |