summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2005-02-13 06:23:13 +0000
committeralc <alc@FreeBSD.org>2005-02-13 06:23:13 +0000
commitd0bed09103cb51294707cdd0a99306d0a6c7abef (patch)
tree56182c0c07ba6889dcd380bc24c283fa12eaf1e2
parent9f778d1e48a6750547459224a180ae3ff08dfb24 (diff)
downloadFreeBSD-src-d0bed09103cb51294707cdd0a99306d0a6c7abef.zip
FreeBSD-src-d0bed09103cb51294707cdd0a99306d0a6c7abef.tar.gz
Implement support for CPU private mappings within sf_buf_alloc().
-rw-r--r--sys/i386/i386/vm_machdep.c33
-rw-r--r--sys/i386/include/sf_buf.h5
2 files changed, 37 insertions, 1 deletions
diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c
index 0bd0cba..4323442 100644
--- a/sys/i386/i386/vm_machdep.c
+++ b/sys/i386/i386/vm_machdep.c
@@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$");
#include <machine/md_var.h>
#include <machine/pcb.h>
#include <machine/pcb_ext.h>
+#include <machine/smp.h>
#include <machine/vm86.h>
#ifdef CPU_ELAN
@@ -610,8 +611,13 @@ sf_buf_alloc(struct vm_page *m, int flags)
pt_entry_t opte, *ptep;
struct sf_head *hash_list;
struct sf_buf *sf;
+#ifdef SMP
+ cpumask_t cpumask, other_cpus;
+#endif
int error;
+ KASSERT(curthread->td_pinned > 0 || (flags & SFB_CPUPRIVATE) == 0,
+ ("sf_buf_alloc(SFB_CPUPRIVATE): curthread not pinned"));
hash_list = &sf_buf_active[SF_BUF_HASH(m)];
mtx_lock(&sf_buf_lock);
LIST_FOREACH(sf, hash_list, list_entry) {
@@ -622,6 +628,22 @@ sf_buf_alloc(struct vm_page *m, int flags)
nsfbufsused++;
nsfbufspeak = imax(nsfbufspeak, nsfbufsused);
}
+#ifdef SMP
+ cpumask = PCPU_GET(cpumask);
+ if ((sf->cpumask & cpumask) == 0) {
+ sf->cpumask |= cpumask;
+ invlpg(sf->kva);
+ }
+ if ((flags & SFB_CPUPRIVATE) == 0) {
+ other_cpus = PCPU_GET(other_cpus) & ~sf->cpumask;
+ if (other_cpus != 0) {
+ sf->cpumask |= other_cpus;
+ mtx_lock_spin(&smp_ipi_mtx);
+ smp_masked_invlpg(other_cpus, sf->kva);
+ mtx_unlock_spin(&smp_ipi_mtx);
+ }
+ }
+#endif
goto done;
}
}
@@ -660,6 +682,17 @@ sf_buf_alloc(struct vm_page *m, int flags)
ptep = vtopte(sf->kva);
opte = *ptep;
*ptep = VM_PAGE_TO_PHYS(m) | pgeflag | PG_RW | PG_V;
+#ifdef SMP
+ if (flags & SFB_CPUPRIVATE) {
+ if ((opte & (PG_A | PG_V)) == (PG_A | PG_V)) {
+ sf->cpumask = PCPU_GET(cpumask);
+ invlpg(sf->kva);
+ } else
+ sf->cpumask = all_cpus;
+ goto done;
+ } else
+ sf->cpumask = all_cpus;
+#endif
if ((opte & (PG_A | PG_V)) == (PG_A | PG_V))
pmap_invalidate_page(kernel_pmap, sf->kva);
done:
diff --git a/sys/i386/include/sf_buf.h b/sys/i386/include/sf_buf.h
index 7d438f0..9076260 100644
--- a/sys/i386/include/sf_buf.h
+++ b/sys/i386/include/sf_buf.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003 Alan L. Cox <alc@cs.rice.edu>
+ * Copyright (c) 2003, 2005 Alan L. Cox <alc@cs.rice.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,6 +39,9 @@ struct sf_buf {
struct vm_page *m; /* currently mapped page */
vm_offset_t kva; /* va of mapping */
int ref_count; /* usage of this mapping */
+#ifdef SMP
+ cpumask_t cpumask; /* cpus on which mapping is valid */
+#endif
};
static __inline vm_offset_t
OpenPOWER on IntegriCloud