Changeset View
Standalone View
sys/arm64/arm64/pmap.c
Show First 20 Lines • Show All 284 Lines • ▼ Show 20 Lines | |||||||||||
vm_paddr_t dmap_phys_base; /* The start of the dmap region */ | vm_paddr_t dmap_phys_base; /* The start of the dmap region */ | ||||||||||
vm_paddr_t dmap_phys_max; /* The limit of the dmap region */ | vm_paddr_t dmap_phys_max; /* The limit of the dmap region */ | ||||||||||
vm_offset_t dmap_max_addr; /* The virtual address limit of the dmap */ | vm_offset_t dmap_max_addr; /* The virtual address limit of the dmap */ | ||||||||||
/* This code assumes all L1 DMAP entries will be used */ | /* This code assumes all L1 DMAP entries will be used */ | ||||||||||
CTASSERT((DMAP_MIN_ADDRESS & ~L0_OFFSET) == DMAP_MIN_ADDRESS); | CTASSERT((DMAP_MIN_ADDRESS & ~L0_OFFSET) == DMAP_MIN_ADDRESS); | ||||||||||
CTASSERT((DMAP_MAX_ADDRESS & ~L0_OFFSET) == DMAP_MAX_ADDRESS); | CTASSERT((DMAP_MAX_ADDRESS & ~L0_OFFSET) == DMAP_MAX_ADDRESS); | ||||||||||
#define DMAP_TABLES ((DMAP_MAX_ADDRESS - DMAP_MIN_ADDRESS) >> L0_SHIFT) | extern pt_entry_t pagetable_l0_ttbr1[]; | ||||||||||
extern pt_entry_t pagetable_dmap[]; | |||||||||||
#define PHYSMAP_SIZE (2 * (VM_PHYSSEG_MAX - 1)) | #define PHYSMAP_SIZE (2 * (VM_PHYSSEG_MAX - 1)) | ||||||||||
static vm_paddr_t physmap[PHYSMAP_SIZE]; | static vm_paddr_t physmap[PHYSMAP_SIZE]; | ||||||||||
static u_int physmap_idx; | static u_int physmap_idx; | ||||||||||
static SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, | static SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, | ||||||||||
"VM/pmap parameters"); | "VM/pmap parameters"); | ||||||||||
▲ Show 20 Lines • Show All 500 Lines • ▼ Show 20 Lines | |||||||||||
pmap_early_vtophys(vm_offset_t va) | pmap_early_vtophys(vm_offset_t va) | ||||||||||
{ | { | ||||||||||
vm_paddr_t pa_page; | vm_paddr_t pa_page; | ||||||||||
pa_page = arm64_address_translate_s1e1r(va) & PAR_PA_MASK; | pa_page = arm64_address_translate_s1e1r(va) & PAR_PA_MASK; | ||||||||||
return (pa_page | (va & PAR_LOW_MASK)); | return (pa_page | (va & PAR_LOW_MASK)); | ||||||||||
} | } | ||||||||||
static vm_offset_t | /* State of the bootstrapped DMAP page tables */ | ||||||||||
pmap_bootstrap_dmap_l2(vm_offset_t *va, vm_paddr_t *pa, u_int *prev_l1_slot, | struct dmap_bootstrap_state { | ||||||||||
markj: `va` doesn't need to be a pointer. | |||||||||||
Done Inline Actionspmap_bootstrap_dmap_l1() updates freemempos directly. It would be nice to be consistent. markj: pmap_bootstrap_dmap_l1() updates freemempos directly. It would be nice to be consistent. | |||||||||||
pt_entry_t **l2p, int i, vm_offset_t freemempos) | vm_offset_t va; | ||||||||||
{ | vm_paddr_t pa; | ||||||||||
pt_entry_t *l1; | |||||||||||
pt_entry_t *l2; | pt_entry_t *l2; | ||||||||||
pt_entry_t *l3; | |||||||||||
u_int l0_slot; | |||||||||||
u_int l1_slot; | |||||||||||
u_int l2_slot; | |||||||||||
vm_offset_t freemempos; | |||||||||||
}; | |||||||||||
static void | |||||||||||
pmap_bootstrap_dmap_l0_table(struct dmap_bootstrap_state *state) | |||||||||||
{ | |||||||||||
vm_paddr_t l1_pa; | |||||||||||
u_int l0_slot; | |||||||||||
/* Link the level 0 table to a level 1 table */ | |||||||||||
l0_slot = pmap_l0_index(state->va); | |||||||||||
if (l0_slot != state->l0_slot) { | |||||||||||
Done Inline ActionsRather than this bit-masking operation, I would argue for asserting that l1 (or *freemempos) is page aligned. If l1 isn't page aligned, then the problems will go beyond a bogus l0 table entry. alc: Rather than this bit-masking operation, I would argue for asserting that l1 (or *freemempos) is… | |||||||||||
MPASS(state->l0_slot < l0_slot || | |||||||||||
state->l0_slot == L0_ENTRIES); | |||||||||||
/* Create a new L0 table entry */ | |||||||||||
state->l0_slot = l0_slot; | |||||||||||
state->l1 = (pt_entry_t *)state->freemempos; | |||||||||||
memset(state->l1, 0, PAGE_SIZE); | |||||||||||
Done Inline ActionsCan't this assignment be inside the above if statement? alc: Can't this assignment be inside the above if statement? | |||||||||||
state->freemempos += PAGE_SIZE; | |||||||||||
/* Reset lower levels */ | |||||||||||
Not Done Inline ActionsI would suggest doing the zeroing before hooking the page into the page table. Otherwise, when I see things done in this order, I pause and ponder if there might be a possible problem/race. alc: I would suggest doing the zeroing before hooking the page into the page table. Otherwise, when… | |||||||||||
state->l2 = NULL; | |||||||||||
state->l3 = NULL; | |||||||||||
state->l1_slot = Ln_ENTRIES; | |||||||||||
state->l2_slot = Ln_ENTRIES; | |||||||||||
l1_pa = pmap_early_vtophys((vm_offset_t)state->l1); | |||||||||||
MPASS((l1_pa & Ln_TABLE_MASK) == 0); | |||||||||||
MPASS(pagetable_l0_ttbr1[l0_slot] == 0); | |||||||||||
pmap_store(&pagetable_l0_ttbr1[l0_slot], l1_pa | | |||||||||||
TATTR_UXN_TABLE | TATTR_AP_TABLE_NO_EL0 | L0_TABLE); | |||||||||||
} | |||||||||||
KASSERT(state->l1 != NULL, ("%s: NULL l1", __func__)); | |||||||||||
} | |||||||||||
static void | |||||||||||
pmap_bootstrap_dmap_l1_table(struct dmap_bootstrap_state *state) | |||||||||||
{ | |||||||||||
vm_paddr_t l2_pa; | vm_paddr_t l2_pa; | ||||||||||
u_int l1_slot, l2_slot; | u_int l1_slot; | ||||||||||
bool first; | |||||||||||
l2 = *l2p; | /* Make sure there is a valid L0 -> L1 table */ | ||||||||||
l1_slot = ((*va - DMAP_MIN_ADDRESS) >> L1_SHIFT); | pmap_bootstrap_dmap_l0_table(state); | ||||||||||
if (l1_slot != *prev_l1_slot) { | |||||||||||
*prev_l1_slot = l1_slot; | |||||||||||
l2 = (pt_entry_t *)freemempos; | |||||||||||
l2_pa = pmap_early_vtophys((vm_offset_t)l2); | |||||||||||
freemempos += PAGE_SIZE; | |||||||||||
pmap_store(&pagetable_dmap[l1_slot], | /* Link the level 1 table to a level 2 table */ | ||||||||||
(l2_pa & ~Ln_TABLE_MASK) | | l1_slot = pmap_l1_index(state->va); | ||||||||||
TATTR_PXN_TABLE | L1_TABLE); | if (l1_slot != state->l1_slot) { | ||||||||||
MPASS(state->l1_slot < l1_slot || | |||||||||||
state->l1_slot == Ln_ENTRIES); | |||||||||||
memset(l2, 0, PAGE_SIZE); | /* Create a new L1 table entry */ | ||||||||||
state->l1_slot = l1_slot; | |||||||||||
state->l2 = (pt_entry_t *)state->freemempos; | |||||||||||
memset(state->l2, 0, PAGE_SIZE); | |||||||||||
state->freemempos += PAGE_SIZE; | |||||||||||
/* Reset lower levels */ | |||||||||||
state->l3 = NULL; | |||||||||||
state->l2_slot = Ln_ENTRIES; | |||||||||||
l2_pa = pmap_early_vtophys((vm_offset_t)state->l2); | |||||||||||
MPASS((l2_pa & Ln_TABLE_MASK) == 0); | |||||||||||
MPASS(state->l1[l1_slot] == 0); | |||||||||||
pmap_store(&state->l1[l1_slot], l2_pa | TATTR_PXN_TABLE | | |||||||||||
L1_TABLE); | |||||||||||
} | } | ||||||||||
KASSERT(l2 != NULL, | KASSERT(state->l2 != NULL, ("%s: NULL l2", __func__)); | ||||||||||
("pmap_bootstrap_dmap_l2: NULL l2 map")); | } | ||||||||||
for (first = true; *va < DMAP_MAX_ADDRESS && *pa < physmap[i + 1]; | |||||||||||
*pa += L2_SIZE, *va += L2_SIZE) { | static void | ||||||||||
pmap_bootstrap_dmap_l2_table(struct dmap_bootstrap_state *state) | |||||||||||
{ | |||||||||||
vm_paddr_t l3_pa; | |||||||||||
u_int l2_slot; | |||||||||||
/* Make sure there is a valid L1 -> L2 table */ | |||||||||||
pmap_bootstrap_dmap_l1_table(state); | |||||||||||
Not Done Inline ActionsPlease swap the order of these two lines for consistency with pmap_bootstrap_dmap_l1(). alc: Please swap the order of these two lines for consistency with pmap_bootstrap_dmap_l1(). | |||||||||||
/* Link the level 2 table to a level 3 table */ | |||||||||||
l2_slot = pmap_l2_index(state->va); | |||||||||||
if (l2_slot != state->l2_slot) { | |||||||||||
MPASS(state->l2_slot < l2_slot || | |||||||||||
state->l2_slot == Ln_ENTRIES); | |||||||||||
/* Create a new L2 table entry */ | |||||||||||
state->l2_slot = l2_slot; | |||||||||||
state->l3 = (pt_entry_t *)state->freemempos; | |||||||||||
memset(state->l3, 0, PAGE_SIZE); | |||||||||||
state->freemempos += PAGE_SIZE; | |||||||||||
l3_pa = pmap_early_vtophys((vm_offset_t)state->l3); | |||||||||||
MPASS((l3_pa & Ln_TABLE_MASK) == 0); | |||||||||||
MPASS(state->l2[l2_slot] == 0); | |||||||||||
pmap_store(&state->l2[l2_slot], l3_pa | TATTR_PXN_TABLE | | |||||||||||
L2_TABLE); | |||||||||||
Not Done Inline ActionsI would suggest doing the zeroing before hooking the page into the page table. alc: I would suggest doing the zeroing before hooking the page into the page table. | |||||||||||
} | |||||||||||
KASSERT(state->l3 != NULL, ("%s: NULL l3", __func__)); | |||||||||||
} | |||||||||||
static void | |||||||||||
pmap_bootstrap_dmap_l2_block(struct dmap_bootstrap_state *state, int i) | |||||||||||
{ | |||||||||||
u_int l2_slot; | |||||||||||
bool first; | |||||||||||
if ((physmap[i + 1] - state->pa) < L2_SIZE) | |||||||||||
return; | |||||||||||
/* Make sure there is a valid L1 table */ | |||||||||||
pmap_bootstrap_dmap_l1_table(state); | |||||||||||
MPASS((state->va & L2_OFFSET) == 0); | |||||||||||
for (first = true; | |||||||||||
state->va < DMAP_MAX_ADDRESS && | |||||||||||
(physmap[i + 1] - state->pa) >= L2_SIZE; | |||||||||||
state->va += L2_SIZE, state->pa += L2_SIZE) { | |||||||||||
/* | /* | ||||||||||
* Stop if we are about to walk off the end of what the | * Stop if we are about to walk off the end of what the | ||||||||||
* current L1 slot can address. | * current L1 slot can address. | ||||||||||
*/ | */ | ||||||||||
if (!first && (*pa & L1_OFFSET) == 0) | if (!first && (state->pa & L1_OFFSET) == 0) | ||||||||||
break; | break; | ||||||||||
first = false; | first = false; | ||||||||||
l2_slot = pmap_l2_index(*va); | l2_slot = pmap_l2_index(state->va); | ||||||||||
pmap_store(&l2[l2_slot], | MPASS((state->pa & L2_OFFSET) == 0); | ||||||||||
(*pa & ~L2_OFFSET) | ATTR_DEFAULT | | MPASS(state->l2[l2_slot] == 0); | ||||||||||
ATTR_S1_XN | | pmap_store(&state->l2[l2_slot], state->pa | ATTR_DEFAULT | | ||||||||||
ATTR_S1_IDX(VM_MEMATTR_WRITE_BACK) | | ATTR_S1_XN | ATTR_S1_IDX(VM_MEMATTR_WRITE_BACK) | | ||||||||||
L2_BLOCK); | L2_BLOCK); | ||||||||||
} | } | ||||||||||
MPASS(*va == (*pa - dmap_phys_base + DMAP_MIN_ADDRESS)); | MPASS(state->va == (state->pa - dmap_phys_base + DMAP_MIN_ADDRESS)); | ||||||||||
*l2p = l2; | } | ||||||||||
Done Inline ActionsCan't this assignment be inside the above if statement? alc: Can't this assignment be inside the above if statement? | |||||||||||
return (freemempos); | static void | ||||||||||
pmap_bootstrap_dmap_l3_page(struct dmap_bootstrap_state *state, int i) | |||||||||||
{ | |||||||||||
u_int l3_slot; | |||||||||||
bool first; | |||||||||||
Not Done Inline ActionsWe seem to be hitting this assertion: Thread 1 hit Breakpoint 2, pmap_bootstrap_dmap_l2_block (state=state@entry=0xffff000000fa6740, i=i@entry=2) at /usr/home/kyle.evans/freebsd/sys/arm64/arm64/pmap.c:928 928 MPASS((state->va & L2_OFFSET) == 0); (gdb) print *state $1 = {va = 18446638546234179584, pa = 26714636288, l1 = 0xffff000005a24000, l2 = 0xffff000005a25000, l3 = 0xffff000005a26000, l0_slot = 320, l1_slot = 23, l2_slot = 450, freemempos = 18446462598827372544} (gdb) bt #0 pmap_bootstrap_dmap_l2_block (state=state@entry=0xffff000000fa6740, i=i@entry=2) at /usr/home/kyle.evans/freebsd/sys/arm64/arm64/pmap.c:928 #1 0xffff000000776210 in pmap_bootstrap_dmap (freemempos=<optimized out>, kern_l1=<optimized out>, min_pa=<optimized out>) at /usr/home/kyle.evans/freebsd/sys/arm64/arm64/pmap.c:1010 #2 pmap_bootstrap (l0pt=<optimized out>, l1pt=<optimized out>, kernstart=<optimized out>, kernlen=<optimized out>) at /usr/home/kyle.evans/freebsd/sys/arm64/arm64/pmap.c:1158 #3 0xffff000000771c08 in initarm (abp=0xffff000000fa6a60) at /usr/home/kyle.evans/freebsd/sys/arm64/arm64/machdep.c:817 #4 0xffff0000000008b4 in _start () at /usr/home/kyle.evans/freebsd/sys/arm64/arm64/locore.S:152 (gdb) print physmap $2 = {1073741824, 26714046464, 26714505216, 26714636288, 26715291648, 26716274688, 26716995584, 26772373504, 26774011904, 26843545600, 0 <repeats 116 times>} kevans: We seem to be hitting this assertion:
```
Thread 1 hit Breakpoint 2… | |||||||||||
Not Done Inline ActionsAh, a bunch of intermediates were optimized out. Here's this for completeness: (gdb) print *abp $5 = {modulep = 18446462598827315200, kern_l1pt = 18446462598749208576, kern_delta = 18446462572182896640, kern_stack = 18446462598749237248, kern_l0pt = 18446462598749212672, kern_ttbr0 = 26566332416, boot_el = 1, pad = 0} kevans: Ah, a bunch of intermediates were optimized out. Here's this for completeness:
```
(gdb) print… | |||||||||||
if ((physmap[i + 1] - state->pa) < L3_SIZE) | |||||||||||
return; | |||||||||||
/* Make sure there is a valid L2 table */ | |||||||||||
pmap_bootstrap_dmap_l2_table(state); | |||||||||||
MPASS((state->va & L3_OFFSET) == 0); | |||||||||||
for (first = true; | |||||||||||
state->va < DMAP_MAX_ADDRESS && | |||||||||||
(physmap[i + 1] - state->pa) >= L3_SIZE; | |||||||||||
state->va += L3_SIZE, state->pa += L3_SIZE) { | |||||||||||
/* | |||||||||||
* Stop if we are about to walk off the end of what the | |||||||||||
* current L2 slot can address. | |||||||||||
*/ | |||||||||||
if (!first && (state->pa & L2_OFFSET) == 0) | |||||||||||
break; | |||||||||||
first = false; | |||||||||||
l3_slot = pmap_l3_index(state->va); | |||||||||||
MPASS((state->pa & L3_OFFSET) == 0); | |||||||||||
MPASS(state->l3[l3_slot] == 0); | |||||||||||
pmap_store(&state->l3[l3_slot], state->pa | ATTR_DEFAULT | | |||||||||||
ATTR_S1_XN | ATTR_S1_IDX(VM_MEMATTR_WRITE_BACK) | | |||||||||||
L3_PAGE); | |||||||||||
} | } | ||||||||||
MPASS(state->va == (state->pa - dmap_phys_base + DMAP_MIN_ADDRESS)); | |||||||||||
} | |||||||||||
static vm_offset_t | static vm_offset_t | ||||||||||
pmap_bootstrap_dmap(vm_offset_t kern_l1, vm_paddr_t min_pa, | pmap_bootstrap_dmap(vm_offset_t kern_l1, vm_paddr_t min_pa, | ||||||||||
vm_offset_t freemempos) | vm_offset_t freemempos) | ||||||||||
{ | { | ||||||||||
pt_entry_t *l2; | struct dmap_bootstrap_state state; | ||||||||||
vm_offset_t va; | |||||||||||
vm_paddr_t pa; | |||||||||||
u_int l1_slot, prev_l1_slot; | |||||||||||
int i; | int i; | ||||||||||
dmap_phys_base = min_pa & ~L1_OFFSET; | dmap_phys_base = min_pa & ~L1_OFFSET; | ||||||||||
dmap_phys_max = 0; | dmap_phys_max = 0; | ||||||||||
dmap_max_addr = 0; | dmap_max_addr = 0; | ||||||||||
l2 = NULL; | |||||||||||
prev_l1_slot = -1; | |||||||||||
state.l1 = state.l2 = state.l3 = NULL; | |||||||||||
state.l0_slot = L0_ENTRIES; | |||||||||||
state.l1_slot = Ln_ENTRIES; | |||||||||||
state.l2_slot = Ln_ENTRIES; | |||||||||||
state.freemempos = freemempos; | |||||||||||
Done Inline ActionsLn_ENTRIES seems like a more intuitive sentinel value, if only because these variables are unsigned. markj: Ln_ENTRIES seems like a more intuitive sentinel value, if only because these variables are… | |||||||||||
for (i = 0; i < (physmap_idx * 2); i += 2) { | for (i = 0; i < (physmap_idx * 2); i += 2) { | ||||||||||
pa = physmap[i] & ~L2_OFFSET; | state.pa = physmap[i] & ~L3_OFFSET; | ||||||||||
va = pa - dmap_phys_base + DMAP_MIN_ADDRESS; | state.va = state.pa - dmap_phys_base + DMAP_MIN_ADDRESS; | ||||||||||
/* Create L3 mappings at the start of the region */ | |||||||||||
if ((state.pa & L2_OFFSET) != 0) | |||||||||||
pmap_bootstrap_dmap_l3_page(&state, i); | |||||||||||
Done Inline ActionsWhat if the physmap entry is larger than the region mappable by an L0 slot? markj: What if the physmap entry is larger than the region mappable by an L0 slot? | |||||||||||
MPASS(state.pa <= physmap[i + 1]); | |||||||||||
/* Create L2 mappings at the start of the region */ | /* Create L2 mappings at the start of the region */ | ||||||||||
Not Done Inline Actions
Kyle, try changing this line as above. alc: Kyle, try changing this line as above. | |||||||||||
Not Done Inline ActionsPerfect- we're back to multi-user with this change. Thanks! kevans: Perfect- we're back to multi-user with this change. Thanks! | |||||||||||
if ((pa & L1_OFFSET) != 0) { | if ((state.pa & L1_OFFSET) != 0) | ||||||||||
freemempos = pmap_bootstrap_dmap_l2(&va, &pa, | pmap_bootstrap_dmap_l2_block(&state, i); | ||||||||||
&prev_l1_slot, &l2, i, freemempos); | MPASS(state.pa <= physmap[i + 1]); | ||||||||||
} | |||||||||||
for (; va < DMAP_MAX_ADDRESS && pa < physmap[i + 1] && | /* Create the main L1 block mappings */ | ||||||||||
Not Done Inline ActionsPreviously, this line was required, but with the new pmap_bootstrap_dmap_l2_block() it isn't. Instead, I would suggest putting MPASS(state.pa <= physmap[i + 1]) between each of the cases, i.e., 4K, 2M, 1G, 2M, 4K. alc: Previously, this line was required, but with the new pmap_bootstrap_dmap_l2_block() it isn't. | |||||||||||
(physmap[i + 1] - pa) >= L1_SIZE; | for (; state.va < DMAP_MAX_ADDRESS && | ||||||||||
pa += L1_SIZE, va += L1_SIZE) { | (physmap[i + 1] - state.pa) >= L1_SIZE; | ||||||||||
l1_slot = ((va - DMAP_MIN_ADDRESS) >> L1_SHIFT); | state.va += L1_SIZE, state.pa += L1_SIZE) { | ||||||||||
pmap_store(&pagetable_dmap[l1_slot], | /* Make sure there is a valid L1 table */ | ||||||||||
(pa & ~L1_OFFSET) | ATTR_DEFAULT | ATTR_S1_XN | | pmap_bootstrap_dmap_l0_table(&state); | ||||||||||
ATTR_S1_IDX(VM_MEMATTR_WRITE_BACK) | L1_BLOCK); | MPASS((state.pa & L1_OFFSET) == 0); | ||||||||||
pmap_store(&state.l1[pmap_l1_index(state.va)], | |||||||||||
state.pa | ATTR_DEFAULT | ATTR_S1_XN | | |||||||||||
ATTR_S1_IDX(VM_MEMATTR_WRITE_BACK) | | |||||||||||
L1_BLOCK); | |||||||||||
} | } | ||||||||||
MPASS(state.pa <= physmap[i + 1]); | |||||||||||
/* Create L2 mappings at the end of the region */ | /* Create L2 mappings at the end of the region */ | ||||||||||
if (pa < physmap[i + 1]) { | pmap_bootstrap_dmap_l2_block(&state, i); | ||||||||||
freemempos = pmap_bootstrap_dmap_l2(&va, &pa, | MPASS(state.pa <= physmap[i + 1]); | ||||||||||
&prev_l1_slot, &l2, i, freemempos); | |||||||||||
} | |||||||||||
if (pa > dmap_phys_max) { | /* Create L3 mappings at the end of the region */ | ||||||||||
dmap_phys_max = pa; | pmap_bootstrap_dmap_l3_page(&state, i); | ||||||||||
Not Done Inline ActionsShouldn't this be >=? alc: Shouldn't this be `>=`? | |||||||||||
dmap_max_addr = va; | MPASS(state.pa == physmap[i + 1]); | ||||||||||
Not Done Inline ActionsShouldn't this be >=? alc: Shouldn't this be `>=`? | |||||||||||
if (state.pa > dmap_phys_max) { | |||||||||||
dmap_phys_max = state.pa; | |||||||||||
dmap_max_addr = state.va; | |||||||||||
} | } | ||||||||||
} | } | ||||||||||
cpu_tlb_flushID(); | cpu_tlb_flushID(); | ||||||||||
return (freemempos); | return (state.freemempos); | ||||||||||
} | } | ||||||||||
static vm_offset_t | static vm_offset_t | ||||||||||
pmap_bootstrap_l2(vm_offset_t l1pt, vm_offset_t va, vm_offset_t l2_start) | pmap_bootstrap_l2(vm_offset_t l1pt, vm_offset_t va, vm_offset_t l2_start) | ||||||||||
{ | { | ||||||||||
vm_offset_t l2pt; | vm_offset_t l2pt; | ||||||||||
vm_paddr_t pa; | vm_paddr_t pa; | ||||||||||
pd_entry_t *l1; | pd_entry_t *l1; | ||||||||||
▲ Show 20 Lines • Show All 6,335 Lines • Show Last 20 Lines |
va doesn't need to be a pointer.