diff options
author | alc <alc@FreeBSD.org> | 2005-02-13 06:23:13 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2005-02-13 06:23:13 +0000 |
commit | d0bed09103cb51294707cdd0a99306d0a6c7abef (patch) | |
tree | 56182c0c07ba6889dcd380bc24c283fa12eaf1e2 /sys | |
parent | 9f778d1e48a6750547459224a180ae3ff08dfb24 (diff) | |
download | FreeBSD-src-d0bed09103cb51294707cdd0a99306d0a6c7abef.zip FreeBSD-src-d0bed09103cb51294707cdd0a99306d0a6c7abef.tar.gz |
Implement support for CPU private mappings within sf_buf_alloc().
Diffstat (limited to 'sys')
-rw-r--r-- | sys/i386/i386/vm_machdep.c | 33 | ||||
-rw-r--r-- | sys/i386/include/sf_buf.h | 5 |
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 |