From fb078386873ae8e6cc64382a46e9d47a0ff575e2 Mon Sep 17 00:00:00 2001 From: Artur Grabowski Date: Wed, 5 Dec 2001 14:40:49 +0000 Subject: 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. --- sys/arch/sparc/sparc/cache.c | 154 +++++++++++++++++++++++++----------------- sys/arch/sparc/sparc/cache.h | 10 +-- sys/arch/sparc/sparc/cpu.c | 26 +++---- sys/arch/sparc/sparc/cpuvar.h | 6 +- sys/arch/sparc/sparc/pmap.c | 84 +++++++++++++---------- 5 files changed, 163 insertions(+), 117 deletions(-) (limited to 'sys/arch/sparc') 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 | -- cgit v1.2.3