summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authorjah <jah@FreeBSD.org>2015-08-04 19:46:13 +0000
committerjah <jah@FreeBSD.org>2015-08-04 19:46:13 +0000
commitb8c4d76738c091ce972e522ec36c8dce6642f6fb (patch)
treec099d6990763d6142f37775aa84b5193ad0b77fb /sys/i386
parentd6d829914b43c5cfe1482a423d5466cd717a330c (diff)
downloadFreeBSD-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.c49
-rw-r--r--sys/i386/include/pcpu.h3
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
OpenPOWER on IntegriCloud