diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2001-12-05 14:40:49 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2001-12-05 14:40:49 +0000 |
commit | fb078386873ae8e6cc64382a46e9d47a0ff575e2 (patch) | |
tree | 89623cf3edb5b28967cc527bd1d49f47586027f4 /sys/arch/sparc | |
parent | 756f8426b1096d558626d3c3e8056b9ab4587f0f (diff) |
Change pcache_flush_line to pcache_flush_page since this is the only way
we use the function.
At the same time fix the pte pool backend functions to allocate and map
the memory themselves.
Diffstat (limited to 'sys/arch/sparc')
-rw-r--r-- | sys/arch/sparc/sparc/cache.c | 154 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/cache.h | 10 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/cpu.c | 26 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/cpuvar.h | 6 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/pmap.c | 84 |
5 files changed, 163 insertions, 117 deletions
diff --git a/sys/arch/sparc/sparc/cache.c b/sys/arch/sparc/sparc/cache.c index 28baedda260..be40c5ae1c8 100644 --- a/sys/arch/sparc/sparc/cache.c +++ b/sys/arch/sparc/sparc/cache.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cache.c,v 1.13 2000/03/17 21:54:07 deraadt Exp $ */ +/* $OpenBSD: cache.c,v 1.14 2001/12/05 14:40:48 art Exp $ */ /* $NetBSD: cache.c,v 1.34 1997/09/26 22:17:23 pk Exp $ */ /* @@ -768,72 +768,102 @@ viking_cache_flush(base, len) } void -viking_pcache_flush_line(va, pa) - int va; - int pa; +viking_pcache_flush_page(pa, invalidate_only) + paddr_t pa; + int invalidate_only; { - /* - * Flush cache line corresponding to virtual address `va' - * which is mapped at physical address `pa'. - */ - extern char etext[]; - static char *base; - int i; - char *v; + int set, i; /* - * Construct a virtual address that hits the same cache line - * as PA, then read from 2*ASSOCIATIVITY-1 different physical - * locations (all different from PA). + * The viking's on-chip data cache is 4-way set associative, + * consisting of 128 sets, each holding 4 lines of 32 bytes. + * Note that one 4096 byte page exactly covers all 128 sets + * in the cache. */ + if (invalidate_only) { + u_int pa_tag = (pa >> 12); + u_int tagaddr; + u_int64_t tag; + + /* + * Loop over all sets and invalidate all entries tagged + * with the given physical address by resetting the cache + * tag in ASI_DCACHETAG control space. + * + * The address format for accessing a tag is: + * + * 31 30 27 26 11 5 4 3 2 0 + * +------+-----+------+-------//--------+--------+----+-----+ + * | type | xxx | line | xxx | set | xx | 0 | + * +------+-----+------+-------//--------+--------+----+-----+ + * + * set: the cache set tag to be read (0-127) + * line: the line within the set (0-3) + * type: 1: read set tag; 2: read physical tag + * + * The (type 2) tag read from this address is a 64-bit word + * formatted as follows: + * + * 5 4 4 + * 63 6 8 0 23 0 + * +-------+-+-------+-+-------+-+-----------+----------------+ + * | xxx |V| xxx |D| xxx |S| xxx | PA[35-12] | + * +-------+-+-------+-+-------+-+-----------+----------------+ + * + * PA: bits 12-35 of the physical address + * S: line shared bit + * D: line dirty bit + * V: line valid bit + */ + +#define VIKING_DCACHETAG_S 0x0000010000000000UL /* line valid bit */ +#define VIKING_DCACHETAG_D 0x0001000000000000UL /* line dirty bit */ +#define VIKING_DCACHETAG_V 0x0100000000000000UL /* line shared bit */ +#define VIKING_DCACHETAG_PAMASK 0x0000000000ffffffUL /* PA tag field */ + + for (set = 0; set < 128; set++) { + /* Set set number and access type */ + tagaddr = (set << 5) | (2 << 30); + + /* Examine the tag for each line in the set */ + for (i = 0 ; i < 4; i++) { + tag = ldda(tagaddr | (i << 26), ASI_DCACHETAG); + /* + * If this is a valid tag and the PA field + * matches clear the tag. + */ + if ((tag & VIKING_DCACHETAG_PAMASK) == pa_tag && + (tag & VIKING_DCACHETAG_V) != 0) + stda(tagaddr | (i << 26), + ASI_DCACHETAG, 0); + } + } -#if 0 - if (base == 0) { - cshift = CACHEINFO.ic_l2linesize; - csize = CACHEINFO.ic_nlines << cshift; - cmask = csize - 1; - base = (char *)roundup((int)etext, csize); - } - - v = base + (((va & cmask) >> cshift) << cshift); - i = CACHEINFO.dc_associativity * 2 - 1; - - while (i--) { - (*(volatile int *)v); - v += csize; - } -#else -#define cshift 5 /* CACHEINFO.ic_l2linesize */ -#define csize (128 << cshift) /* CACHEINFO.ic_nlines << cshift */ -#define cmask (csize - 1) -#define cass 4 /* CACHEINFO.dc_associativity */ - - if (base == 0) - base = (char *)roundup((unsigned int)etext, csize); - - v = base + (((pa & cmask) >> cshift) << cshift); - i = 2 * cass - 1; - - while (i--) { - (*(volatile int *)v); - v += csize; + } else { + extern char kernel_text[]; + + /* + * Force the cache to validate its backing memory + * by displacing all cache lines with known read-only + * content from the start of kernel text. + * + * Note that this thrashes the entire cache. However, + * we currently only need to call upon this code + * once at boot time. + */ + for (set = 0; set < 128; set++) { + int *v = (int *)(kernel_text + (set << 5)); + + /* + * We need to read (2*associativity-1) different + * locations to be sure to displace the entire set. + */ + i = 2 * 4 - 1; + while (i--) { + (*(volatile int *)v); + v += 4096; + } + } } -#undef cass -#undef cmask -#undef csize -#undef cshift -#endif -} - -void -srmmu_pcache_flush_line(va, pa) - int va; - int pa; -{ - /* - * Flush cache line corresponding to virtual address `va' - * which is mapped at physical address `pa'. - */ - sta(va, ASI_IDCACHELFP, 0); } #endif /* SUN4M */ diff --git a/sys/arch/sparc/sparc/cache.h b/sys/arch/sparc/sparc/cache.h index 58b7ef7f743..445ec2369f8 100644 --- a/sys/arch/sparc/sparc/cache.h +++ b/sys/arch/sparc/sparc/cache.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cache.h,v 1.4 2000/02/19 21:45:56 art Exp $ */ +/* $OpenBSD: cache.h,v 1.5 2001/12/05 14:40:48 art Exp $ */ /* $NetBSD: cache.h,v 1.16 1997/07/06 21:15:14 pk Exp $ */ /* @@ -178,8 +178,7 @@ void hypersparc_cache_flush_all __P((void)); void ms1_cache_flush __P((caddr_t, u_int)); void viking_cache_flush __P((caddr_t, u_int)); -void viking_pcache_flush_line __P((int, int)); -void srmmu_pcache_flush_line __P((int, int)); +void viking_pcache_flush_page __P((paddr_t, int)); extern void sparc_noop __P((void)); @@ -193,8 +192,8 @@ extern void sparc_noop __P((void)); (void (*)__P((int))) sparc_noop #define noop_cache_flush \ (void (*)__P((caddr_t, u_int))) sparc_noop -#define noop_pcache_flush_line \ - (void (*)__P((int, int))) sparc_noop +#define noop_pcache_flush_page \ + (void (*)__P((paddr_t, int))) sparc_noop #define noop_pure_vcache_flush \ (void (*)__P((void))) sparc_noop #define noop_cache_flush_all \ @@ -204,6 +203,7 @@ extern void sparc_noop __P((void)); #define cache_flush_segment(vr,vs) cpuinfo.vcache_flush_segment(vr,vs) #define cache_flush_region(vr) cpuinfo.vcache_flush_region(vr) #define cache_flush_context() cpuinfo.vcache_flush_context() +#define pcache_flush_page(pa,flag) cpuinfo.pcache_flush_page(pa,flag) /* * Cache control information. diff --git a/sys/arch/sparc/sparc/cpu.c b/sys/arch/sparc/sparc/cpu.c index 39cc7540799..b6835308192 100644 --- a/sys/arch/sparc/sparc/cpu.c +++ b/sys/arch/sparc/sparc/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.33 2001/11/06 19:53:16 miod Exp $ */ +/* $OpenBSD: cpu.c,v 1.34 2001/12/05 14:40:48 art Exp $ */ /* $NetBSD: cpu.c,v 1.56 1997/09/15 20:52:36 pk Exp $ */ /* @@ -429,7 +429,7 @@ struct module_info module_sun4 = { sun4_vcache_flush_segment, sun4_vcache_flush_region, sun4_vcache_flush_context, - noop_pcache_flush_line, + noop_pcache_flush_page, noop_pure_vcache_flush, noop_cache_flush_all, 0 @@ -555,7 +555,7 @@ struct module_info module_sun4c = { sun4_vcache_flush_segment, sun4_vcache_flush_region, sun4_vcache_flush_context, - noop_pcache_flush_line, + noop_pcache_flush_page, noop_pure_vcache_flush, noop_cache_flush_all, 0 @@ -753,7 +753,7 @@ struct module_info module_ms1 = { noop_vcache_flush_segment, noop_vcache_flush_region, noop_vcache_flush_context, - noop_pcache_flush_line, + noop_pcache_flush_page, noop_pure_vcache_flush, ms1_cache_flush_all, memerr4m @@ -781,7 +781,7 @@ struct module_info module_ms2 = { srmmu_vcache_flush_segment, srmmu_vcache_flush_region, srmmu_vcache_flush_context, - noop_pcache_flush_line, + noop_pcache_flush_page, noop_pure_vcache_flush, srmmu_cache_flush_all, memerr4m @@ -804,7 +804,7 @@ struct module_info module_swift = { srmmu_vcache_flush_segment, srmmu_vcache_flush_region, srmmu_vcache_flush_context, - srmmu_pcache_flush_line, + noop_pcache_flush_page, noop_pure_vcache_flush, srmmu_cache_flush_all, memerr4m @@ -852,7 +852,7 @@ struct module_info module_viking = { noop_vcache_flush_segment, noop_vcache_flush_region, noop_vcache_flush_context, - viking_pcache_flush_line, + viking_pcache_flush_page, noop_pure_vcache_flush, noop_cache_flush_all, viking_memerr @@ -890,7 +890,7 @@ viking_hotfix(sc) sc->flags |= CPUFLG_CACHEPAGETABLES; } else { sc->cache_flush = viking_cache_flush; - sc->pcache_flush_line = viking_pcache_flush_line; + sc->pcache_flush_page = viking_pcache_flush_page; } /* XXX! */ @@ -935,7 +935,7 @@ struct module_info module_hypersparc = { srmmu_vcache_flush_segment, srmmu_vcache_flush_region, srmmu_vcache_flush_context, - srmmu_pcache_flush_line, + noop_pcache_flush_page, hypersparc_pure_vcache_flush, hypersparc_cache_flush_all, hypersparc_memerr @@ -986,7 +986,7 @@ struct module_info module_cypress = { srmmu_vcache_flush_segment, srmmu_vcache_flush_region, srmmu_vcache_flush_context, - srmmu_pcache_flush_line, + noop_pcache_flush_page, noop_pure_vcache_flush, cypress_cache_flush_all, memerr4m @@ -1009,7 +1009,7 @@ struct module_info module_turbosparc = { /* UNTESTED */ srmmu_vcache_flush_segment, srmmu_vcache_flush_region, srmmu_vcache_flush_context, - srmmu_pcache_flush_line, + noop_pcache_flush_page, noop_pure_vcache_flush, srmmu_cache_flush_all, memerr4m @@ -1047,7 +1047,7 @@ cpumatch_turbosparc(sc, mp, node) sc->vcache_flush_segment = 0; sc->vcache_flush_region = 0; sc->vcache_flush_context = 0; - sc->pcache_flush_line = 0; + sc->pcache_flush_page = 0; replacemul(); } @@ -1234,7 +1234,7 @@ getcpuinfo(sc, node) MPCOPY(vcache_flush_segment); MPCOPY(vcache_flush_region); MPCOPY(vcache_flush_context); - MPCOPY(pcache_flush_line); + MPCOPY(pcache_flush_page); MPCOPY(pure_vcache_flush); MPCOPY(cache_flush_all); MPCOPY(memerr); diff --git a/sys/arch/sparc/sparc/cpuvar.h b/sys/arch/sparc/sparc/cpuvar.h index 2f430f1711e..003a745ed0b 100644 --- a/sys/arch/sparc/sparc/cpuvar.h +++ b/sys/arch/sparc/sparc/cpuvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpuvar.h,v 1.4 2000/02/21 17:08:36 art Exp $ */ +/* $OpenBSD: cpuvar.h,v 1.5 2001/12/05 14:40:48 art Exp $ */ /* $NetBSD: cpuvar.h,v 1.4 1997/07/06 21:14:25 pk Exp $ */ /* @@ -70,7 +70,7 @@ struct module_info { void (*vcache_flush_segment) __P((int, int)); void (*vcache_flush_region) __P((int)); void (*vcache_flush_context) __P((void)); - void (*pcache_flush_line) __P((int, int)); + void (*pcache_flush_page) __P((paddr_t, int)); void (*pure_vcache_flush) __P((void)); void (*cache_flush_all)__P((void)); void (*memerr) __P((unsigned, u_int, u_int, struct trapframe *)); @@ -183,7 +183,7 @@ struct cpu_softc { void (*vcache_flush_segment)__P((int, int)); void (*vcache_flush_region)__P((int)); void (*vcache_flush_context)__P((void)); - void (*pcache_flush_line)__P((int, int)); + void (*pcache_flush_page)__P((paddr_t, int)); void (*pure_vcache_flush) __P((void)); void (*cache_flush_all)__P((void)); diff --git a/sys/arch/sparc/sparc/pmap.c b/sys/arch/sparc/sparc/pmap.c index cad323178dd..fb5142c9cc0 100644 --- a/sys/arch/sparc/sparc/pmap.c +++ b/sys/arch/sparc/sparc/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.100 2001/11/28 15:34:16 art Exp $ */ +/* $OpenBSD: pmap.c,v 1.101 2001/12/05 14:40:48 art Exp $ */ /* $NetBSD: pmap.c,v 1.118 1998/05/19 19:00:18 thorpej Exp $ */ /* @@ -217,18 +217,6 @@ static struct pool L23_pool; void *pgt_page_alloc __P((unsigned long, int, int)); void pgt_page_free __P((void *, unsigned long, int)); -void pcache_flush __P((caddr_t, caddr_t, int)); -void -pcache_flush(va, pa, n) - caddr_t va, pa; - int n; -{ - void (*f)__P((int,int)) = cpuinfo.pcache_flush_line; - - while ((n -= 4) >= 0) - (*f)((u_int)va+n, (u_int)pa+n); -} - /* * Page table pool back-end. */ @@ -238,16 +226,26 @@ pgt_page_alloc(sz, flags, mtype) int flags; int mtype; { - caddr_t p; + struct vm_page *pg; + int nocache = (cpuinfo.flags & CPUFLG_CACHEPAGETABLES) == 0; + vaddr_t va; + paddr_t pa; - p = (caddr_t)uvm_km_kmemalloc(kernel_map, uvm.kernel_object, - (vsize_t)sz, UVM_KMF_NOWAIT); + if ((pg = uvm_pagealloc(NULL, 0, NULL, 0)) == NULL) + return (NULL); - if (p != NULL && ((cpuinfo.flags & CPUFLG_CACHEPAGETABLES) == 0)) { - pcache_flush(p, (caddr_t)VA2PA(p), sz); - kvm_uncache(p, atop(sz)); - } - return (p); + if ((va = uvm_km_valloc(kernel_map, PAGE_SIZE)) == 0) { + uvm_pagefree(pg); + return (NULL); + } + + pa = VM_PAGE_TO_PHYS(pg); + if (nocache) + pcache_flush_page(pa, 1); + + pmap_kenter_pa(va, pa | (nocache ? PMAP_NC : 0), + VM_PROT_READ|VM_PROT_WRITE); + return ((void *)va); } void @@ -3233,11 +3231,32 @@ pmap_bootstrap4m(void) cpuinfo.ctx_tbl[i] = cpuinfo.ctx_tbl[0]; #endif - if ((cpuinfo.flags & CPUFLG_CACHEPAGETABLES) == 0) - /* Flush page tables from cache */ - pcache_flush((caddr_t)pagetables_start, - (caddr_t)VA2PA((caddr_t)pagetables_start), - pagetables_end - pagetables_start); + if ((cpuinfo.flags & CPUFLG_CACHEPAGETABLES) == 0) { + /* + * The page tables have been setup. Since we're still + * running on the PROM's memory map, the memory we + * allocated for our page tables might still be cached. + * Flush it now, and don't touch it again until we + * switch to our own tables (will be done immediately below). + */ + int size = pagetables_end - pagetables_start; + + if (CACHEINFO.c_vactype != VAC_NONE) { + int va = (vaddr_t)pagetables_start; + while (size != 0) { + cache_flush_page(va); + va += NBPG; + size -= NBPG; + } + } else if (cpuinfo.pcache_flush_page != NULL) { + int pa = pagetables_start; + while (size != 0) { + pcache_flush_page(pa, 0); + pa += NBPG; + size -= NBPG; + } + } + } /* * Now switch to kernel pagetables (finally!) @@ -5994,14 +6013,11 @@ pmap_zero_page4m(pa) if (ptep == NULL) ptep = getptep4m(pmap_kernel(), (va = (vaddr_t)vpage[0])); - if (pmap_initialized && (pv = pvhead(atop(pa))) != NULL && - CACHEINFO.c_vactype != VAC_NONE) { - /* - * The following might not be necessary since the page - * is being cleared because it is about to be allocated, - * i.e., is in use by no one. - */ - pv_flushcache(pv); + if (pmap_initialized && (pv = pvhead(atop(pa))) != NULL) { + if (CACHEINFO.c_vactype != VAC_NONE) + pv_flushcache(pv); + else + pcache_flush_page(pa, 1); } pte = (SRMMU_TEPTE | PPROT_S | PPROT_WRITE | |