diff options
author | jah <jah@FreeBSD.org> | 2015-08-04 19:46:13 +0000 |
---|---|---|
committer | jah <jah@FreeBSD.org> | 2015-08-04 19:46:13 +0000 |
commit | b8c4d76738c091ce972e522ec36c8dce6642f6fb (patch) | |
tree | c099d6990763d6142f37775aa84b5193ad0b77fb /sys/i386 | |
parent | d6d829914b43c5cfe1482a423d5466cd717a330c (diff) | |
download | FreeBSD-src-b8c4d76738c091ce972e522ec36c8dce6642f6fb.zip FreeBSD-src-b8c4d76738c091ce972e522ec36c8dce6642f6fb.tar.gz |
Add two new pmap functions:
vm_offset_t pmap_quick_enter_page(vm_page_t m)
void pmap_quick_remove_page(vm_offset_t kva)
These will create and destroy a temporary, CPU-local KVA mapping of a specified page.
Guarantees:
--Will not sleep and will not fail.
--Safe to call under a non-sleepable lock or from an ithread
Restrictions:
--Not guaranteed to be safe to call from an interrupt filter or under a spin mutex on all platforms
--Current implementation does not guarantee more than one page of mapping space across all platforms. MI code should not make nested calls to pmap_quick_enter_page.
--MI code should not perform locking while holding onto a mapping created by pmap_quick_enter_page
The idea is to use this in busdma, for bounce buffer copies as well as virtually-indexed cache maintenance on mips and arm.
NOTE: the non-i386, non-amd64 implementations of these functions still need review and testing.
Reviewed by: kib
Approved by: kib (mentor)
Differential Revision: http://reviews.freebsd.org/D3013
Diffstat (limited to 'sys/i386')
-rw-r--r-- | sys/i386/i386/pmap.c | 49 | ||||
-rw-r--r-- | sys/i386/include/pcpu.h | 3 |
2 files changed, 51 insertions, 1 deletions
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index b02311e..efd44b3 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -512,6 +512,22 @@ pmap_bootstrap(vm_paddr_t firstaddr) pmap_set_pg(); } +static void +pmap_init_qpages(void) +{ + struct pcpu *pc; + int i; + + CPU_FOREACH(i) { + pc = pcpu_find(i); + pc->pc_qmap_addr = kva_alloc(PAGE_SIZE); + if (pc->pc_qmap_addr == 0) + panic("pmap_init_qpages: unable to allocate KVA"); + } +} + +SYSINIT(qpages_init, SI_SUB_CPU, SI_ORDER_ANY, pmap_init_qpages, NULL); + /* * Setup the PAT MSR. */ @@ -5400,6 +5416,39 @@ pmap_align_superpage(vm_object_t object, vm_ooffset_t offset, *addr = ((*addr + PDRMASK) & ~PDRMASK) + superpage_offset; } +vm_offset_t +pmap_quick_enter_page(vm_page_t m) +{ + vm_offset_t qaddr; + pt_entry_t *pte; + + critical_enter(); + qaddr = PCPU_GET(qmap_addr); + pte = vtopte(qaddr); + + KASSERT(*pte == 0, ("pmap_quick_enter_page: PTE busy")); + *pte = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M | + pmap_cache_bits(pmap_page_get_memattr(m), 0); + invlpg(qaddr); + + return (qaddr); +} + +void +pmap_quick_remove_page(vm_offset_t addr) +{ + vm_offset_t qaddr; + pt_entry_t *pte; + + qaddr = PCPU_GET(qmap_addr); + pte = vtopte(qaddr); + + KASSERT(*pte != 0, ("pmap_quick_remove_page: PTE not in use")); + KASSERT(addr == qaddr, ("pmap_quick_remove_page: invalid address")); + + *pte = 0; + critical_exit(); +} #if defined(PMAP_DEBUG) pmap_pid_dump(int pid) diff --git a/sys/i386/include/pcpu.h b/sys/i386/include/pcpu.h index 231f80f..cfd8d03 100644 --- a/sys/i386/include/pcpu.h +++ b/sys/i386/include/pcpu.h @@ -58,7 +58,8 @@ int pc_private_tss; /* Flag indicating private tss*/\ u_int pc_cmci_mask; /* MCx banks for CMCI */ \ u_int pc_vcpu_id; /* Xen vCPU ID */ \ - char __pad[233] + vm_offset_t pc_qmap_addr; /* KVA for temporary mappings */\ + char __pad[229] #ifdef _KERNEL |