Changeset View
Changeset View
Standalone View
Standalone View
sys/i386/i386/pmap.c
Show First 20 Lines • Show All 1,033 Lines • ▼ Show 20 Lines | |||||
static u_long pmap_pde_promotions; | static u_long pmap_pde_promotions; | ||||
SYSCTL_ULONG(_vm_pmap_pde, OID_AUTO, promotions, CTLFLAG_RD, | SYSCTL_ULONG(_vm_pmap_pde, OID_AUTO, promotions, CTLFLAG_RD, | ||||
&pmap_pde_promotions, 0, "2/4MB page promotions"); | &pmap_pde_promotions, 0, "2/4MB page promotions"); | ||||
/*************************************************** | /*************************************************** | ||||
* Low level helper routines..... | * Low level helper routines..... | ||||
***************************************************/ | ***************************************************/ | ||||
boolean_t | |||||
pmap_is_valid_memattr(pmap_t pmap __unused, vm_memattr_t mode) | |||||
{ | |||||
return (mode >= 0 && mode < PAT_INDEX_SIZE && | |||||
pat_index[(int)mode] >= 0); | |||||
} | |||||
/* | /* | ||||
* Determine the appropriate bits to set in a PTE or PDE for a specified | * Determine the appropriate bits to set in a PTE or PDE for a specified | ||||
* caching mode. | * caching mode. | ||||
*/ | */ | ||||
int | int | ||||
pmap_cache_bits(int mode, boolean_t is_pde) | pmap_cache_bits(pmap_t pmap, int mode, boolean_t is_pde) | ||||
{ | { | ||||
int cache_bits, pat_flag, pat_idx; | int cache_bits, pat_flag, pat_idx; | ||||
if (mode < 0 || mode >= PAT_INDEX_SIZE || pat_index[mode] < 0) | if (!pmap_is_valid_memattr(pmap, mode)) | ||||
panic("Unknown caching mode %d\n", mode); | panic("Unknown caching mode %d\n", mode); | ||||
/* The PAT bit is different for PTE's and PDE's. */ | /* The PAT bit is different for PTE's and PDE's. */ | ||||
pat_flag = is_pde ? PG_PDE_PAT : PG_PTE_PAT; | pat_flag = is_pde ? PG_PDE_PAT : PG_PTE_PAT; | ||||
/* Map the caching mode to a PAT index. */ | /* Map the caching mode to a PAT index. */ | ||||
pat_idx = pat_index[mode]; | pat_idx = pat_index[mode]; | ||||
▲ Show 20 Lines • Show All 653 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static __inline void | static __inline void | ||||
pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode) | pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode) | ||||
{ | { | ||||
pt_entry_t *pte; | pt_entry_t *pte; | ||||
pte = vtopte(va); | pte = vtopte(va); | ||||
pte_store(pte, pa | PG_RW | PG_V | pmap_cache_bits(mode, 0)); | pte_store(pte, pa | PG_RW | PG_V | pmap_cache_bits(kernel_pmap, | ||||
mode, 0)); | |||||
} | } | ||||
/* | /* | ||||
* Remove a page from the kernel pagetables. | * Remove a page from the kernel pagetables. | ||||
* Note: not SMP coherent. | * Note: not SMP coherent. | ||||
* | * | ||||
* This function may be used before pmap_bootstrap() is called. | * This function may be used before pmap_bootstrap() is called. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | pmap_qenter(vm_offset_t sva, vm_page_t *ma, int count) | ||||
pt_entry_t *endpte, oldpte, pa, *pte; | pt_entry_t *endpte, oldpte, pa, *pte; | ||||
vm_page_t m; | vm_page_t m; | ||||
oldpte = 0; | oldpte = 0; | ||||
pte = vtopte(sva); | pte = vtopte(sva); | ||||
endpte = pte + count; | endpte = pte + count; | ||||
while (pte < endpte) { | while (pte < endpte) { | ||||
m = *ma++; | m = *ma++; | ||||
pa = VM_PAGE_TO_PHYS(m) | pmap_cache_bits(m->md.pat_mode, 0); | pa = VM_PAGE_TO_PHYS(m) | pmap_cache_bits(kernel_pmap, | ||||
m->md.pat_mode, 0); | |||||
if ((*pte & (PG_FRAME | PG_PTE_CACHE)) != pa) { | if ((*pte & (PG_FRAME | PG_PTE_CACHE)) != pa) { | ||||
oldpte |= *pte; | oldpte |= *pte; | ||||
#if defined(PAE) || defined(PAE_TABLES) | #if defined(PAE) || defined(PAE_TABLES) | ||||
pte_store(pte, pa | pg_nx | PG_RW | PG_V); | pte_store(pte, pa | pg_nx | PG_RW | PG_V); | ||||
#else | #else | ||||
pte_store(pte, pa | PG_RW | PG_V); | pte_store(pte, pa | PG_RW | PG_V); | ||||
#endif | #endif | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,886 Lines • ▼ Show 20 Lines | pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, | ||||
*/ | */ | ||||
if (wired) | if (wired) | ||||
pmap->pm_stats.wired_count++; | pmap->pm_stats.wired_count++; | ||||
validate: | validate: | ||||
/* | /* | ||||
* Now validate mapping with desired protection/wiring. | * Now validate mapping with desired protection/wiring. | ||||
*/ | */ | ||||
newpte = (pt_entry_t)(pa | pmap_cache_bits(m->md.pat_mode, 0) | PG_V); | newpte = (pt_entry_t)(pa | pmap_cache_bits(pmap, m->md.pat_mode, 0) | | ||||
PG_V); | |||||
if ((prot & VM_PROT_WRITE) != 0) { | if ((prot & VM_PROT_WRITE) != 0) { | ||||
newpte |= PG_RW; | newpte |= PG_RW; | ||||
if ((newpte & PG_MANAGED) != 0) | if ((newpte & PG_MANAGED) != 0) | ||||
vm_page_aflag_set(m, PGA_WRITEABLE); | vm_page_aflag_set(m, PGA_WRITEABLE); | ||||
} | } | ||||
#if defined(PAE) || defined(PAE_TABLES) | #if defined(PAE) || defined(PAE_TABLES) | ||||
if ((prot & VM_PROT_EXECUTE) == 0) | if ((prot & VM_PROT_EXECUTE) == 0) | ||||
newpte |= pg_nx; | newpte |= pg_nx; | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | pmap_enter_pde(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot) | ||||
rw_assert(&pvh_global_lock, RA_WLOCKED); | rw_assert(&pvh_global_lock, RA_WLOCKED); | ||||
PMAP_LOCK_ASSERT(pmap, MA_OWNED); | PMAP_LOCK_ASSERT(pmap, MA_OWNED); | ||||
pde = pmap_pde(pmap, va); | pde = pmap_pde(pmap, va); | ||||
if (*pde != 0) { | if (*pde != 0) { | ||||
CTR2(KTR_PMAP, "pmap_enter_pde: failure for va %#lx" | CTR2(KTR_PMAP, "pmap_enter_pde: failure for va %#lx" | ||||
" in pmap %p", va, pmap); | " in pmap %p", va, pmap); | ||||
return (FALSE); | return (FALSE); | ||||
} | } | ||||
newpde = VM_PAGE_TO_PHYS(m) | pmap_cache_bits(m->md.pat_mode, 1) | | newpde = VM_PAGE_TO_PHYS(m) | pmap_cache_bits(pmap, m->md.pat_mode, 1) | | ||||
PG_PS | PG_V; | PG_PS | PG_V; | ||||
if ((m->oflags & VPO_UNMANAGED) == 0) { | if ((m->oflags & VPO_UNMANAGED) == 0) { | ||||
newpde |= PG_MANAGED; | newpde |= PG_MANAGED; | ||||
/* | /* | ||||
* Abort this mapping if its PV entry could not be created. | * Abort this mapping if its PV entry could not be created. | ||||
*/ | */ | ||||
if (!pmap_pv_insert_pde(pmap, va, VM_PAGE_TO_PHYS(m))) { | if (!pmap_pv_insert_pde(pmap, va, VM_PAGE_TO_PHYS(m))) { | ||||
▲ Show 20 Lines • Show All 171 Lines • ▼ Show 20 Lines | if ((m->oflags & VPO_UNMANAGED) == 0 && | ||||
return (mpte); | return (mpte); | ||||
} | } | ||||
/* | /* | ||||
* Increment counters | * Increment counters | ||||
*/ | */ | ||||
pmap->pm_stats.resident_count++; | pmap->pm_stats.resident_count++; | ||||
pa = VM_PAGE_TO_PHYS(m) | pmap_cache_bits(m->md.pat_mode, 0); | pa = VM_PAGE_TO_PHYS(m) | pmap_cache_bits(pmap, m->md.pat_mode, 0); | ||||
#if defined(PAE) || defined(PAE_TABLES) | #if defined(PAE) || defined(PAE_TABLES) | ||||
if ((prot & VM_PROT_EXECUTE) == 0) | if ((prot & VM_PROT_EXECUTE) == 0) | ||||
pa |= pg_nx; | pa |= pg_nx; | ||||
#endif | #endif | ||||
/* | /* | ||||
* Now validate mapping with RO protection | * Now validate mapping with RO protection | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | if (pseflag && | ||||
} | } | ||||
/* | /* | ||||
* Map using 2/4MB pages. Since "ptepa" is 2/4M aligned and | * Map using 2/4MB pages. Since "ptepa" is 2/4M aligned and | ||||
* "size" is a multiple of 2/4M, adding the PAT setting to | * "size" is a multiple of 2/4M, adding the PAT setting to | ||||
* "pa" will not affect the termination of this loop. | * "pa" will not affect the termination of this loop. | ||||
*/ | */ | ||||
PMAP_LOCK(pmap); | PMAP_LOCK(pmap); | ||||
for (pa = ptepa | pmap_cache_bits(pat_mode, 1); pa < ptepa + | for (pa = ptepa | pmap_cache_bits(pmap, pat_mode, 1); | ||||
size; pa += NBPDR) { | pa < ptepa + size; pa += NBPDR) { | ||||
pde = pmap_pde(pmap, addr); | pde = pmap_pde(pmap, addr); | ||||
if (*pde == 0) { | if (*pde == 0) { | ||||
pde_store(pde, pa | PG_PS | PG_M | PG_A | | pde_store(pde, pa | PG_PS | PG_M | PG_A | | ||||
PG_U | PG_RW | PG_V); | PG_U | PG_RW | PG_V); | ||||
pmap->pm_stats.resident_count += NBPDR / | pmap->pm_stats.resident_count += NBPDR / | ||||
PAGE_SIZE; | PAGE_SIZE; | ||||
pmap_pde_mappings++; | pmap_pde_mappings++; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 248 Lines • ▼ Show 20 Lines | pmap_zero_page(vm_page_t m) | ||||
sched_pin(); | sched_pin(); | ||||
pc = get_pcpu(); | pc = get_pcpu(); | ||||
cmap_pte2 = pc->pc_cmap_pte2; | cmap_pte2 = pc->pc_cmap_pte2; | ||||
mtx_lock(&pc->pc_cmap_lock); | mtx_lock(&pc->pc_cmap_lock); | ||||
if (*cmap_pte2) | if (*cmap_pte2) | ||||
panic("pmap_zero_page: CMAP2 busy"); | panic("pmap_zero_page: CMAP2 busy"); | ||||
*cmap_pte2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M | | *cmap_pte2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M | | ||||
pmap_cache_bits(m->md.pat_mode, 0); | pmap_cache_bits(kernel_pmap, m->md.pat_mode, 0); | ||||
invlcaddr(pc->pc_cmap_addr2); | invlcaddr(pc->pc_cmap_addr2); | ||||
pagezero(pc->pc_cmap_addr2); | pagezero(pc->pc_cmap_addr2); | ||||
*cmap_pte2 = 0; | *cmap_pte2 = 0; | ||||
/* | /* | ||||
* Unpin the thread before releasing the lock. Otherwise the thread | * Unpin the thread before releasing the lock. Otherwise the thread | ||||
* could be rescheduled while still bound to the current CPU, only | * could be rescheduled while still bound to the current CPU, only | ||||
* to unpin itself immediately upon resuming execution. | * to unpin itself immediately upon resuming execution. | ||||
Show All 14 Lines | pmap_zero_page_area(vm_page_t m, int off, int size) | ||||
sched_pin(); | sched_pin(); | ||||
pc = get_pcpu(); | pc = get_pcpu(); | ||||
cmap_pte2 = pc->pc_cmap_pte2; | cmap_pte2 = pc->pc_cmap_pte2; | ||||
mtx_lock(&pc->pc_cmap_lock); | mtx_lock(&pc->pc_cmap_lock); | ||||
if (*cmap_pte2) | if (*cmap_pte2) | ||||
panic("pmap_zero_page_area: CMAP2 busy"); | panic("pmap_zero_page_area: CMAP2 busy"); | ||||
*cmap_pte2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M | | *cmap_pte2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M | | ||||
pmap_cache_bits(m->md.pat_mode, 0); | pmap_cache_bits(kernel_pmap, m->md.pat_mode, 0); | ||||
invlcaddr(pc->pc_cmap_addr2); | invlcaddr(pc->pc_cmap_addr2); | ||||
if (off == 0 && size == PAGE_SIZE) | if (off == 0 && size == PAGE_SIZE) | ||||
pagezero(pc->pc_cmap_addr2); | pagezero(pc->pc_cmap_addr2); | ||||
else | else | ||||
bzero(pc->pc_cmap_addr2 + off, size); | bzero(pc->pc_cmap_addr2 + off, size); | ||||
*cmap_pte2 = 0; | *cmap_pte2 = 0; | ||||
sched_unpin(); | sched_unpin(); | ||||
mtx_unlock(&pc->pc_cmap_lock); | mtx_unlock(&pc->pc_cmap_lock); | ||||
Show All 13 Lines | pmap_copy_page(vm_page_t src, vm_page_t dst) | ||||
cmap_pte1 = pc->pc_cmap_pte1; | cmap_pte1 = pc->pc_cmap_pte1; | ||||
cmap_pte2 = pc->pc_cmap_pte2; | cmap_pte2 = pc->pc_cmap_pte2; | ||||
mtx_lock(&pc->pc_cmap_lock); | mtx_lock(&pc->pc_cmap_lock); | ||||
if (*cmap_pte1) | if (*cmap_pte1) | ||||
panic("pmap_copy_page: CMAP1 busy"); | panic("pmap_copy_page: CMAP1 busy"); | ||||
if (*cmap_pte2) | if (*cmap_pte2) | ||||
panic("pmap_copy_page: CMAP2 busy"); | panic("pmap_copy_page: CMAP2 busy"); | ||||
*cmap_pte1 = PG_V | VM_PAGE_TO_PHYS(src) | PG_A | | *cmap_pte1 = PG_V | VM_PAGE_TO_PHYS(src) | PG_A | | ||||
pmap_cache_bits(src->md.pat_mode, 0); | pmap_cache_bits(kernel_pmap, src->md.pat_mode, 0); | ||||
invlcaddr(pc->pc_cmap_addr1); | invlcaddr(pc->pc_cmap_addr1); | ||||
*cmap_pte2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(dst) | PG_A | PG_M | | *cmap_pte2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(dst) | PG_A | PG_M | | ||||
pmap_cache_bits(dst->md.pat_mode, 0); | pmap_cache_bits(kernel_pmap, dst->md.pat_mode, 0); | ||||
invlcaddr(pc->pc_cmap_addr2); | invlcaddr(pc->pc_cmap_addr2); | ||||
bcopy(pc->pc_cmap_addr1, pc->pc_cmap_addr2, PAGE_SIZE); | bcopy(pc->pc_cmap_addr1, pc->pc_cmap_addr2, PAGE_SIZE); | ||||
*cmap_pte1 = 0; | *cmap_pte1 = 0; | ||||
*cmap_pte2 = 0; | *cmap_pte2 = 0; | ||||
sched_unpin(); | sched_unpin(); | ||||
mtx_unlock(&pc->pc_cmap_lock); | mtx_unlock(&pc->pc_cmap_lock); | ||||
} | } | ||||
Show All 22 Lines | pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[], | ||||
while (xfersize > 0) { | while (xfersize > 0) { | ||||
a_pg = ma[a_offset >> PAGE_SHIFT]; | a_pg = ma[a_offset >> PAGE_SHIFT]; | ||||
a_pg_offset = a_offset & PAGE_MASK; | a_pg_offset = a_offset & PAGE_MASK; | ||||
cnt = min(xfersize, PAGE_SIZE - a_pg_offset); | cnt = min(xfersize, PAGE_SIZE - a_pg_offset); | ||||
b_pg = mb[b_offset >> PAGE_SHIFT]; | b_pg = mb[b_offset >> PAGE_SHIFT]; | ||||
b_pg_offset = b_offset & PAGE_MASK; | b_pg_offset = b_offset & PAGE_MASK; | ||||
cnt = min(cnt, PAGE_SIZE - b_pg_offset); | cnt = min(cnt, PAGE_SIZE - b_pg_offset); | ||||
*cmap_pte1 = PG_V | VM_PAGE_TO_PHYS(a_pg) | PG_A | | *cmap_pte1 = PG_V | VM_PAGE_TO_PHYS(a_pg) | PG_A | | ||||
pmap_cache_bits(a_pg->md.pat_mode, 0); | pmap_cache_bits(kernel_pmap, a_pg->md.pat_mode, 0); | ||||
invlcaddr(pc->pc_cmap_addr1); | invlcaddr(pc->pc_cmap_addr1); | ||||
*cmap_pte2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(b_pg) | PG_A | | *cmap_pte2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(b_pg) | PG_A | | ||||
PG_M | pmap_cache_bits(b_pg->md.pat_mode, 0); | PG_M | pmap_cache_bits(kernel_pmap, b_pg->md.pat_mode, 0); | ||||
invlcaddr(pc->pc_cmap_addr2); | invlcaddr(pc->pc_cmap_addr2); | ||||
a_cp = pc->pc_cmap_addr1 + a_pg_offset; | a_cp = pc->pc_cmap_addr1 + a_pg_offset; | ||||
b_cp = pc->pc_cmap_addr2 + b_pg_offset; | b_cp = pc->pc_cmap_addr2 + b_pg_offset; | ||||
bcopy(a_cp, b_cp, cnt); | bcopy(a_cp, b_cp, cnt); | ||||
a_offset += cnt; | a_offset += cnt; | ||||
b_offset += cnt; | b_offset += cnt; | ||||
xfersize -= cnt; | xfersize -= cnt; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 955 Lines • ▼ Show 20 Lines | pmap_flush_page(vm_page_t m) | ||||
if (useclflushopt || (cpu_feature & CPUID_CLFSH) != 0) { | if (useclflushopt || (cpu_feature & CPUID_CLFSH) != 0) { | ||||
sched_pin(); | sched_pin(); | ||||
pc = get_pcpu(); | pc = get_pcpu(); | ||||
cmap_pte2 = pc->pc_cmap_pte2; | cmap_pte2 = pc->pc_cmap_pte2; | ||||
mtx_lock(&pc->pc_cmap_lock); | mtx_lock(&pc->pc_cmap_lock); | ||||
if (*cmap_pte2) | if (*cmap_pte2) | ||||
panic("pmap_flush_page: CMAP2 busy"); | panic("pmap_flush_page: CMAP2 busy"); | ||||
*cmap_pte2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | | *cmap_pte2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | | ||||
PG_A | PG_M | pmap_cache_bits(m->md.pat_mode, 0); | PG_A | PG_M | pmap_cache_bits(kernel_pmap, m->md.pat_mode, | ||||
0); | |||||
invlcaddr(pc->pc_cmap_addr2); | invlcaddr(pc->pc_cmap_addr2); | ||||
sva = (vm_offset_t)pc->pc_cmap_addr2; | sva = (vm_offset_t)pc->pc_cmap_addr2; | ||||
eva = sva + PAGE_SIZE; | eva = sva + PAGE_SIZE; | ||||
/* | /* | ||||
* Use mfence or sfence despite the ordering implied by | * Use mfence or sfence despite the ordering implied by | ||||
* mtx_{un,}lock() because clflush on non-Intel CPUs | * mtx_{un,}lock() because clflush on non-Intel CPUs | ||||
* and clflushopt are not guaranteed to be ordered by | * and clflushopt are not guaranteed to be ordered by | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | pmap_change_attr(vm_offset_t va, vm_size_t size, int mode) | ||||
size = round_page(offset + size); | size = round_page(offset + size); | ||||
/* | /* | ||||
* Only supported on kernel virtual addresses above the recursive map. | * Only supported on kernel virtual addresses above the recursive map. | ||||
*/ | */ | ||||
if (base < VM_MIN_KERNEL_ADDRESS) | if (base < VM_MIN_KERNEL_ADDRESS) | ||||
return (EINVAL); | return (EINVAL); | ||||
cache_bits_pde = pmap_cache_bits(mode, 1); | cache_bits_pde = pmap_cache_bits(kernel_pmap, mode, 1); | ||||
cache_bits_pte = pmap_cache_bits(mode, 0); | cache_bits_pte = pmap_cache_bits(kernel_pmap, mode, 0); | ||||
changed = FALSE; | changed = FALSE; | ||||
/* | /* | ||||
* Pages that aren't mapped aren't supported. Also break down | * Pages that aren't mapped aren't supported. Also break down | ||||
* 2/4MB pages into 4KB pages if required. | * 2/4MB pages into 4KB pages if required. | ||||
*/ | */ | ||||
PMAP_LOCK(kernel_pmap); | PMAP_LOCK(kernel_pmap); | ||||
for (tmpva = base; tmpva < base + size; ) { | for (tmpva = base; tmpva < base + size; ) { | ||||
▲ Show 20 Lines • Show All 189 Lines • ▼ Show 20 Lines | pmap_quick_enter_page(vm_page_t m) | ||||
pt_entry_t *pte; | pt_entry_t *pte; | ||||
critical_enter(); | critical_enter(); | ||||
qaddr = PCPU_GET(qmap_addr); | qaddr = PCPU_GET(qmap_addr); | ||||
pte = vtopte(qaddr); | pte = vtopte(qaddr); | ||||
KASSERT(*pte == 0, ("pmap_quick_enter_page: PTE busy")); | KASSERT(*pte == 0, ("pmap_quick_enter_page: PTE busy")); | ||||
*pte = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M | | *pte = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M | | ||||
pmap_cache_bits(pmap_page_get_memattr(m), 0); | pmap_cache_bits(kernel_pmap, pmap_page_get_memattr(m), 0); | ||||
invlpg(qaddr); | invlpg(qaddr); | ||||
return (qaddr); | return (qaddr); | ||||
} | } | ||||
void | void | ||||
pmap_quick_remove_page(vm_offset_t addr) | pmap_quick_remove_page(vm_offset_t addr) | ||||
{ | { | ||||
Show All 34 Lines | pmap_trm_import(void *unused __unused, vmem_size_t size, int flags, | ||||
} | } | ||||
prev_addr += trm_guard; | prev_addr += trm_guard; | ||||
trm_pte = PTmap + atop(prev_addr); | trm_pte = PTmap + atop(prev_addr); | ||||
for (af = prev_addr; af < addr; af += PAGE_SIZE) { | for (af = prev_addr; af < addr; af += PAGE_SIZE) { | ||||
m = vm_page_alloc(NULL, 0, VM_ALLOC_NOOBJ | VM_ALLOC_NOBUSY | | m = vm_page_alloc(NULL, 0, VM_ALLOC_NOOBJ | VM_ALLOC_NOBUSY | | ||||
VM_ALLOC_NORMAL | VM_ALLOC_WIRED | VM_ALLOC_WAITOK); | VM_ALLOC_NORMAL | VM_ALLOC_WIRED | VM_ALLOC_WAITOK); | ||||
pte_store(&trm_pte[atop(af - prev_addr)], VM_PAGE_TO_PHYS(m) | | pte_store(&trm_pte[atop(af - prev_addr)], VM_PAGE_TO_PHYS(m) | | ||||
PG_M | PG_A | PG_RW | PG_V | pgeflag | | PG_M | PG_A | PG_RW | PG_V | pgeflag | | ||||
pmap_cache_bits(VM_MEMATTR_DEFAULT, FALSE)); | pmap_cache_bits(kernel_pmap, VM_MEMATTR_DEFAULT, FALSE)); | ||||
} | } | ||||
*addrp = prev_addr; | *addrp = prev_addr; | ||||
return (0); | return (0); | ||||
} | } | ||||
static | static | ||||
void pmap_init_trm(void) | void pmap_init_trm(void) | ||||
{ | { | ||||
vm_page_t pd_m; | vm_page_t pd_m; | ||||
TUNABLE_INT_FETCH("machdep.trm_guard", &trm_guard); | TUNABLE_INT_FETCH("machdep.trm_guard", &trm_guard); | ||||
if ((trm_guard & PAGE_MASK) != 0) | if ((trm_guard & PAGE_MASK) != 0) | ||||
trm_guard = 0; | trm_guard = 0; | ||||
pmap_trm_arena = vmem_create("i386trampoline", 0, 0, 1, 0, M_WAITOK); | pmap_trm_arena = vmem_create("i386trampoline", 0, 0, 1, 0, M_WAITOK); | ||||
vmem_set_import(pmap_trm_arena, pmap_trm_import, NULL, NULL, PAGE_SIZE); | vmem_set_import(pmap_trm_arena, pmap_trm_import, NULL, NULL, PAGE_SIZE); | ||||
pd_m = vm_page_alloc(NULL, 0, VM_ALLOC_NOOBJ | VM_ALLOC_NOBUSY | | pd_m = vm_page_alloc(NULL, 0, VM_ALLOC_NOOBJ | VM_ALLOC_NOBUSY | | ||||
VM_ALLOC_NORMAL | VM_ALLOC_WIRED | VM_ALLOC_WAITOK | VM_ALLOC_ZERO); | VM_ALLOC_NORMAL | VM_ALLOC_WIRED | VM_ALLOC_WAITOK | VM_ALLOC_ZERO); | ||||
if ((pd_m->flags & PG_ZERO) == 0) | if ((pd_m->flags & PG_ZERO) == 0) | ||||
pmap_zero_page(pd_m); | pmap_zero_page(pd_m); | ||||
PTD[TRPTDI] = VM_PAGE_TO_PHYS(pd_m) | PG_M | PG_A | PG_RW | PG_V | | PTD[TRPTDI] = VM_PAGE_TO_PHYS(pd_m) | PG_M | PG_A | PG_RW | PG_V | | ||||
pmap_cache_bits(VM_MEMATTR_DEFAULT, TRUE); | pmap_cache_bits(kernel_pmap, VM_MEMATTR_DEFAULT, TRUE); | ||||
} | } | ||||
void * | void * | ||||
pmap_trm_alloc(size_t size, int flags) | pmap_trm_alloc(size_t size, int flags) | ||||
{ | { | ||||
vmem_addr_t res; | vmem_addr_t res; | ||||
int error; | int error; | ||||
▲ Show 20 Lines • Show All 77 Lines • Show Last 20 Lines |