Changeset View
Changeset View
Standalone View
Standalone View
sys/arm64/arm64/pmap.c
Show First 20 Lines • Show All 121 Lines • ▼ Show 20 Lines | |||||
#include <sys/rwlock.h> | #include <sys/rwlock.h> | ||||
#include <sys/sx.h> | #include <sys/sx.h> | ||||
#include <sys/vmem.h> | #include <sys/vmem.h> | ||||
#include <sys/vmmeter.h> | #include <sys/vmmeter.h> | ||||
#include <sys/sched.h> | #include <sys/sched.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/_unrhdr.h> | #include <sys/_unrhdr.h> | ||||
#include <sys/smp.h> | #include <sys/smp.h> | ||||
#include <sys/efi.h> | |||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/vm_param.h> | #include <vm/vm_param.h> | ||||
#include <vm/vm_kern.h> | #include <vm/vm_kern.h> | ||||
#include <vm/vm_page.h> | #include <vm/vm_page.h> | ||||
#include <vm/vm_map.h> | #include <vm/vm_map.h> | ||||
#include <vm/vm_object.h> | #include <vm/vm_object.h> | ||||
#include <vm/vm_extern.h> | #include <vm/vm_extern.h> | ||||
Show All 31 Lines | |||||
/* | /* | ||||
* These are configured by the mair_el1 register. This is set up in locore.S | * These are configured by the mair_el1 register. This is set up in locore.S | ||||
*/ | */ | ||||
#define DEVICE_MEMORY 0 | #define DEVICE_MEMORY 0 | ||||
#define UNCACHED_MEMORY 1 | #define UNCACHED_MEMORY 1 | ||||
#define CACHED_MEMORY 2 | #define CACHED_MEMORY 2 | ||||
#ifdef PV_STATS | #ifdef PV_STATS | ||||
#define PV_STAT(x) do { x ; } while (0) | #define PV_STAT(x) do { x ; } while (0) | ||||
#else | #else | ||||
#define PV_STAT(x) do { } while (0) | #define PV_STAT(x) do { } while (0) | ||||
#endif | #endif | ||||
#define pmap_l2_pindex(v) ((v) >> L2_SHIFT) | #define pmap_l2_pindex(v) ((v) >> L2_SHIFT) | ||||
#define pa_to_pvh(pa) (&pv_table[pmap_l2_pindex(pa)]) | #define pa_to_pvh(pa) (&pv_table[pmap_l2_pindex(pa)]) | ||||
▲ Show 20 Lines • Show All 968 Lines • ▼ Show 20 Lines | |||||
void | void | ||||
pmap_kenter(vm_offset_t sva, vm_size_t size, vm_paddr_t pa, int mode) | pmap_kenter(vm_offset_t sva, vm_size_t size, vm_paddr_t pa, int mode) | ||||
{ | { | ||||
pd_entry_t *pde; | pd_entry_t *pde; | ||||
pt_entry_t *pte, attr; | pt_entry_t *pte, attr; | ||||
vm_offset_t va; | vm_offset_t va; | ||||
int lvl; | int lvl; | ||||
kib: How large is typical map on arm64 ? How many linear walks per page mapping do we add this way ? | |||||
Done Inline ActionsOn the Ampere eMAG it's 25 while on the Pine64 it's 4 and Overdrive 1000 3 it seems. manu: On the Ampere eMAG it's 25 while on the Pine64 it's 4 and Overdrive 1000 3 it seems. | |||||
Not Done Inline ActionsFor me, 25 sounds same as 'a lot'. Since each pmap_kenter() would typically walk some part of the list, depending on the ordering of the elements, I believe it is a good reason to pre-process the map into something more optimal. If you do that, the derived data structure might allow to enter additional items not presented in the raw EFI map, which is good for e.g. purpose of using similar approach on amd64 with non-EFI boot. You might consider using pctrie keyed on the start address of the map element, see sys/pctrie.h. Although the tree will be quite sparse, so may be you can propose something even more optimal. kib: For me, 25 sounds same as 'a lot'. Since each pmap_kenter() would typically walk some part of… | |||||
KASSERT((pa & L3_OFFSET) == 0, | KASSERT((pa & L3_OFFSET) == 0, | ||||
("pmap_kenter: Invalid physical address")); | ("pmap_kenter: Invalid physical address")); | ||||
KASSERT((sva & L3_OFFSET) == 0, | KASSERT((sva & L3_OFFSET) == 0, | ||||
("pmap_kenter: Invalid virtual address")); | ("pmap_kenter: Invalid virtual address")); | ||||
KASSERT((size & PAGE_MASK) == 0, | KASSERT((size & PAGE_MASK) == 0, | ||||
("pmap_kenter: Mapping is not page-sized")); | ("pmap_kenter: Mapping is not page-sized")); | ||||
attr = ATTR_DEFAULT | ATTR_IDX(mode) | L3_PAGE; | attr = ATTR_DEFAULT | ATTR_IDX(mode) | L3_PAGE; | ||||
▲ Show 20 Lines • Show All 3,453 Lines • ▼ Show 20 Lines | |||||
void * | void * | ||||
pmap_mapbios(vm_paddr_t pa, vm_size_t size) | pmap_mapbios(vm_paddr_t pa, vm_size_t size) | ||||
{ | { | ||||
struct pmap_preinit_mapping *ppim; | struct pmap_preinit_mapping *ppim; | ||||
vm_offset_t va, offset; | vm_offset_t va, offset; | ||||
pd_entry_t *pde; | pd_entry_t *pde; | ||||
pt_entry_t *l2; | pt_entry_t *l2; | ||||
uint64_t attr; | |||||
int i, lvl, l2_blocks, free_l2_count, start_idx; | int i, lvl, l2_blocks, free_l2_count, start_idx; | ||||
int mode; | |||||
if (!vm_initialized) { | if (!vm_initialized) { | ||||
/* | /* | ||||
* No L3 ptables so map entire L2 blocks where start VA is: | * No L3 ptables so map entire L2 blocks where start VA is: | ||||
* preinit_map_va + start_idx * L2_SIZE | * preinit_map_va + start_idx * L2_SIZE | ||||
* There may be duplicate mappings (multiple VA -> same PA) but | * There may be duplicate mappings (multiple VA -> same PA) but | ||||
* ARM64 dcache is always PIPT so that's acceptable. | * ARM64 dcache is always PIPT so that's acceptable. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | if (va == 0) | ||||
panic("%s: Couldn't allocate KVA", __func__); | panic("%s: Couldn't allocate KVA", __func__); | ||||
pde = pmap_pde(kernel_pmap, va, &lvl); | pde = pmap_pde(kernel_pmap, va, &lvl); | ||||
KASSERT(lvl == 2, ("pmap_mapbios: Invalid level %d", lvl)); | KASSERT(lvl == 2, ("pmap_mapbios: Invalid level %d", lvl)); | ||||
/* L3 table is linked */ | /* L3 table is linked */ | ||||
va = trunc_page(va); | va = trunc_page(va); | ||||
pa = trunc_page(pa); | pa = trunc_page(pa); | ||||
pmap_kenter(va, size, pa, CACHED_MEMORY); | |||||
/* From UEFI spec 2.8 table 7 in 2.3.6.1 */ | |||||
attr = efi_memory_attribute(pa); | |||||
if ((attr & EFI_MD_ATTR_WB) != 0) | |||||
mode = VM_MEMATTR_WRITE_BACK; | |||||
else if ((attr & EFI_MD_ATTR_WT) != 0) | |||||
mode = VM_MEMATTR_WRITE_THROUGH; | |||||
else if ((attr & EFI_MD_ATTR_WC) != 0) | |||||
mode = VM_MEMATTR_WRITE_COMBINING; | |||||
else | |||||
mode = VM_MEMATTR_DEVICE; | |||||
pmap_kenter(va, size, pa, mode); | |||||
} | } | ||||
return ((void *)(va + offset)); | return ((void *)(va + offset)); | ||||
} | } | ||||
void | void | ||||
pmap_unmapbios(vm_offset_t va, vm_size_t size) | pmap_unmapbios(vm_offset_t va, vm_size_t size) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 684 Lines • Show Last 20 Lines |
How large is typical map on arm64 ? How many linear walks per page mapping do we add this way ?