diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2013-11-16 18:45:21 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2013-11-16 18:45:21 +0000 |
commit | 431731812874189793edce7ce2b5f568e44fc441 (patch) | |
tree | 058097d595daf7e32527caa82bd09f6d039eab6a /sys/arch/m88k | |
parent | 240cdcbabc5239b94c9488aacdae734862dff715 (diff) |
Allow initial device mappings (from pmap_table) to be backed up by BATC.
Use this on luna88k to map the bitmap planes of the frame buffer used by
the driver. 10% speedup under X.
Diffstat (limited to 'sys/arch/m88k')
-rw-r--r-- | sys/arch/m88k/include/cmmu.h | 10 | ||||
-rw-r--r-- | sys/arch/m88k/include/mmu.h | 30 | ||||
-rw-r--r-- | sys/arch/m88k/include/pmap_table.h | 3 | ||||
-rw-r--r-- | sys/arch/m88k/m88k/m8820x_machdep.c | 25 | ||||
-rw-r--r-- | sys/arch/m88k/m88k/pmap.c | 176 |
5 files changed, 193 insertions, 51 deletions
diff --git a/sys/arch/m88k/include/cmmu.h b/sys/arch/m88k/include/cmmu.h index c0b41465b4f..65a2aa2b19c 100644 --- a/sys/arch/m88k/include/cmmu.h +++ b/sys/arch/m88k/include/cmmu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cmmu.h,v 1.31 2013/11/02 23:10:30 miod Exp $ */ +/* $OpenBSD: cmmu.h,v 1.32 2013/11/16 18:45:20 miod Exp $ */ /* * Mach Operating System * Copyright (c) 1993-1992 Carnegie Mellon University @@ -33,6 +33,8 @@ */ #if defined(_KERNEL) && !defined(_LOCORE) +#include <machine/mmu.h> + /* machine dependent cmmu function pointer structure */ struct cmmu_p { cpuid_t (*init)(void); @@ -107,6 +109,12 @@ extern __cpu_simple_lock_t cmmu_cpu_lock; #define DMA_CACHE_SYNC_INVAL 0x01 #define DMA_CACHE_SYNC 0x02 +/* + * Current BATC values. + */ + +extern batc_t global_dbatc[BATC_MAX], global_ibatc[BATC_MAX]; + #endif /* _KERNEL && !_LOCORE */ #endif /* _M88K_CMMU_H_ */ diff --git a/sys/arch/m88k/include/mmu.h b/sys/arch/m88k/include/mmu.h index fddbed446c1..14cdb63a5e4 100644 --- a/sys/arch/m88k/include/mmu.h +++ b/sys/arch/m88k/include/mmu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mmu.h,v 1.14 2013/11/02 23:10:30 miod Exp $ */ +/* $OpenBSD: mmu.h,v 1.15 2013/11/16 18:45:20 miod Exp $ */ /* * This file bears almost no resemblance to the original m68k file, @@ -76,7 +76,7 @@ * Area descriptors */ -typedef u_int32_t apr_t; +typedef uint32_t apr_t; #define APR_V 0x00000001 /* valid bit */ @@ -87,21 +87,10 @@ typedef u_int32_t apr_t; #define PATC_ENTRIES 56 /* - * BATC entries - */ - -#define BATC_V 0x00000001 -#define BATC_PROT 0x00000002 -#define BATC_INH 0x00000004 -#define BATC_GLOBAL 0x00000008 -#define BATC_WT 0x00000010 -#define BATC_SO 0x00000020 - -/* * Segment table entries */ -typedef u_int32_t sdt_entry_t; +typedef uint32_t sdt_entry_t; #define SG_V 0x00000001 #define SG_NV 0x00000000 @@ -118,7 +107,7 @@ typedef u_int32_t sdt_entry_t; * Page table entries */ -typedef u_int32_t pt_entry_t; +typedef uint32_t pt_entry_t; #define PG_V 0x00000001 #define PG_NV 0x00000000 @@ -165,9 +154,18 @@ typedef u_int32_t pt_entry_t; #define PDTIDX(va) (((va) & PDT_MASK) >> PDT_SHIFT) /* - * Parameters and macros for BATC + * BATC entries */ +#define BATC_V 0x00000001 +#define BATC_PROT 0x00000002 +#define BATC_INH 0x00000004 +#define BATC_GLOBAL 0x00000008 +#define BATC_WT 0x00000010 +#define BATC_SO 0x00000020 + +typedef uint32_t batc_t; + /* 8820x fixed size BATC */ #define BATC_BLKSHIFT 19 #define BATC_BLKBYTES (1 << BATC_BLKSHIFT) diff --git a/sys/arch/m88k/include/pmap_table.h b/sys/arch/m88k/include/pmap_table.h index b44097ae7b2..b3a987d4633 100644 --- a/sys/arch/m88k/include/pmap_table.h +++ b/sys/arch/m88k/include/pmap_table.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap_table.h,v 1.4 2011/03/23 16:54:35 pirofti Exp $ */ +/* $OpenBSD: pmap_table.h,v 1.5 2013/11/16 18:45:20 miod Exp $ */ /* * Mach Operating System * Copyright (c) 1992 Carnegie Mellon University @@ -38,6 +38,7 @@ struct pmap_table { psize_t size; vm_prot_t prot; unsigned int cacheability; + boolean_t may_use_batc; }; const struct pmap_table *pmap_table_build(void); diff --git a/sys/arch/m88k/m88k/m8820x_machdep.c b/sys/arch/m88k/m88k/m8820x_machdep.c index 90cf25c5480..32bec51eae8 100644 --- a/sys/arch/m88k/m88k/m8820x_machdep.c +++ b/sys/arch/m88k/m88k/m8820x_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: m8820x_machdep.c,v 1.60 2013/11/03 09:42:55 miod Exp $ */ +/* $OpenBSD: m8820x_machdep.c,v 1.61 2013/11/16 18:45:20 miod Exp $ */ /* * Copyright (c) 2004, 2007, 2010, 2011, 2013, Miodrag Vallat. * @@ -173,8 +173,10 @@ void m8820x_cmmu_inv_locked(int, paddr_t, psize_t); void m8820x_enable_other_cmmu_cache(void); #endif -void m8820x_dbatc_set(cpuid_t, uint, uint32_t); -void m8820x_ibatc_set(cpuid_t, uint, uint32_t); +static inline +void m8820x_dbatc_set(cpuid_t, uint, batc_t); +static inline +void m8820x_ibatc_set(cpuid_t, uint, batc_t); /* Flags passed to m8820x_cmmu_set_*() */ #define MODE_VAL 0x01 @@ -345,14 +347,16 @@ m8820x_cmmu_wait(int cpu) * BATC routines */ +static inline void -m8820x_dbatc_set(cpuid_t cpu, uint batcno, uint32_t batc) +m8820x_dbatc_set(cpuid_t cpu, uint batcno, batc_t batc) { m8820x_cmmu_set_reg_if_mode(CMMU_BWP(batcno), batc, cpu, DATA_CMMU); } +static inline void -m8820x_ibatc_set(cpuid_t cpu, uint batcno, uint32_t batc) +m8820x_ibatc_set(cpuid_t cpu, uint batcno, batc_t batc) { m8820x_cmmu_set_reg_if_mode(CMMU_BWP(batcno), batc, cpu, INST_CMMU); } @@ -362,7 +366,7 @@ m8820x_batc_setup(cpuid_t cpu, apr_t cmode) { paddr_t s_text, e_text, s_data, e_data, e_rodata; uint batcno; - uint32_t batc, proto; + batc_t batc, proto; extern caddr_t kernelstart; extern caddr_t etext; extern caddr_t erodata; @@ -392,7 +396,7 @@ m8820x_batc_setup(cpuid_t cpu, apr_t cmode) #ifdef DEBUG printf("cpu%d ibat%d %p(%08x)\n", cpu, batcno, s_text, batc); #endif - m8820x_ibatc_set(cpu, batcno, batc); + global_ibatc[batcno] = batc; s_text += BATC_BLKBYTES; if (++batcno == BATC_MAX) break; @@ -415,11 +419,16 @@ m8820x_batc_setup(cpuid_t cpu, apr_t cmode) #ifdef DEBUG printf("cpu%d dbat%d %p(%08x)\n", cpu, batcno, s_data, batc); #endif - m8820x_dbatc_set(cpu, batcno, batc); + global_dbatc[batcno] = batc; s_data += BATC_BLKBYTES; if (++batcno == BATC_MAX) break; } + + for (batcno = 0; batcno < BATC_MAX; batcno++) { + m8820x_dbatc_set(cpu, batcno, global_dbatc[batcno]); + m8820x_ibatc_set(cpu, batcno, global_ibatc[batcno]); + } } /* diff --git a/sys/arch/m88k/m88k/pmap.c b/sys/arch/m88k/m88k/pmap.c index a9a73e87ebb..dde3272a098 100644 --- a/sys/arch/m88k/m88k/pmap.c +++ b/sys/arch/m88k/m88k/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.74 2013/11/03 09:42:55 miod Exp $ */ +/* $OpenBSD: pmap.c,v 1.75 2013/11/16 18:45:20 miod Exp $ */ /* * Copyright (c) 2001-2004, 2010, Miodrag Vallat. @@ -148,13 +148,20 @@ paddr_t s_firmware; psize_t l_firmware; /* + * Current BATC values. + */ + +batc_t global_dbatc[BATC_MAX]; +batc_t global_ibatc[BATC_MAX]; + +/* * Internal routines */ void pmap_changebit(struct vm_page *, int, int); void pmap_clean_page(paddr_t); pt_entry_t *pmap_expand(pmap_t, vaddr_t, int); pt_entry_t *pmap_expand_kmap(vaddr_t, int); -void pmap_map(paddr_t, psize_t, vm_prot_t, u_int); +void pmap_map(paddr_t, psize_t, vm_prot_t, u_int, boolean_t); pt_entry_t *pmap_pte(pmap_t, vaddr_t); void pmap_remove_page(struct vm_page *); void pmap_remove_pte(pmap_t, vaddr_t, pt_entry_t *, @@ -242,29 +249,91 @@ int pmap_translation_info(pmap_t pmap, vaddr_t va, paddr_t *pap, uint32_t *ti) { pt_entry_t *pte; + vaddr_t var; + uint batcno; int s; int rv; /* * Check for a BATC translation first. - * Even though we do not use BATC yet, 88100-based designs (with - * 8820x CMMUs) have two hardwired BATC entries which map the - * upper 1MB (so-called `utility space') 1:1 in supervisor space. + * We only use BATC for supervisor mappings (i.e. pmap_kernel()). */ + + if (pmap == pmap_kernel()) { + /* + * 88100-based designs (with 8820x CMMUs) have two hardwired + * BATC entries which map the upper 1MB (so-called + * `utility space') 1:1 in supervisor space. + */ #ifdef M88100 - if (CPU_IS88100 && pmap == pmap_kernel()) { - if (va >= BATC9_VA) { - *pap = va; - *ti = BATC9 & CACHE_MASK; - return PTI_BATC; + if (CPU_IS88100) { + if (va >= BATC9_VA) { + *pap = va; + *ti = 0; + if (BATC9 & BATC_INH) + *ti |= CACHE_INH; + if (BATC9 & BATC_GLOBAL) + *ti |= CACHE_GLOBAL; + if (BATC9 & BATC_WT) + *ti |= CACHE_WT; + return PTI_BATC; + } + if (va >= BATC8_VA) { + *pap = va; + *ti = 0; + if (BATC8 & BATC_INH) + *ti |= CACHE_INH; + if (BATC8 & BATC_GLOBAL) + *ti |= CACHE_GLOBAL; + if (BATC8 & BATC_WT) + *ti |= CACHE_WT; + return PTI_BATC; + } } - if (va >= BATC8_VA) { - *pap = va; - *ti = BATC8 & CACHE_MASK; - return PTI_BATC; +#endif + + /* + * Now try all DBATC entries. + * Note that pmap_translation_info() might be invoked (via + * pmap_extract() ) for instruction faults; we *rely* upon + * the fact that all executable mappings covered by IBATC + * will be: + * - read-only, with no RO->RW upgrade allowed + * - dual mapped by ptes, so that pmap_extract() can still + * return a meaningful result. + * Should this ever change, some kernel interfaces will need + * to be made aware of (and carry on to callees) whether the + * address should be resolved as an instruction or data + * address. + */ + var = trunc_batc(va); + for (batcno = 0; batcno < BATC_MAX; batcno++) { + vaddr_t batcva; + paddr_t batcpa; + batc_t batc; + + batc = global_dbatc[batcno]; + if ((batc & BATC_V) == 0) + continue; + + batcva = (batc << (BATC_BLKSHIFT - BATC_VSHIFT)) & + ~BATC_BLKMASK; + if (batcva == var) { + batcpa = (batc << + (BATC_BLKSHIFT - BATC_PSHIFT)) & + ~BATC_BLKMASK; + *pap = batcpa + (va - var); + *ti = 0; + if (batc & BATC_INH) + *ti |= CACHE_INH; + if (batc & BATC_GLOBAL) + *ti |= CACHE_GLOBAL; + if (batc & BATC_WT) + *ti |= CACHE_WT; + return PTI_BATC; + } } } -#endif /* * Check for a regular PTE translation. @@ -500,11 +569,19 @@ pmap_steal_memory(vsize_t size, vaddr_t *vstartp, vaddr_t *vendp) * [INTERNAL] * Setup a wired mapping in pmap_kernel(). Similar to pmap_kenter_pa(), * but allows explicit cacheability control. + * This is only used at bootstrap time. Mappings may also be backed up + * by a BATC entry if requested and possible; but note that the BATC + * entries set up here may be overwritten by cmmu_batc_setup() later on + * (which is harmless since we are creating proper ptes anyway). */ void -pmap_map(paddr_t pa, psize_t sz, vm_prot_t prot, u_int cmode) +pmap_map(paddr_t pa, psize_t sz, vm_prot_t prot, u_int cmode, + boolean_t may_use_batc) { pt_entry_t *pte, npte; + batc_t batc; + uint npg, batcno; + paddr_t curpa; DPRINTF(CD_MAP, ("pmap_map(%p, %p, %x, %x)\n", pa, sz, prot, cmode)); @@ -514,23 +591,71 @@ pmap_map(paddr_t pa, psize_t sz, vm_prot_t prot, u_int cmode) pa, pa + sz); #endif + sz = round_page(pa + sz) - trunc_page(pa); + pa = trunc_page(pa); + npte = m88k_protection(prot) | cmode | PG_W | PG_V; #ifdef M88110 if (CPU_IS88110 && m88k_protection(prot) != PG_RO) npte |= PG_M; #endif - sz = atop(round_page(pa + sz) - trunc_page(pa)); - pa = trunc_page(pa); - while (sz-- != 0) { - if ((pte = pmap_pte(pmap_kernel(), pa)) == NULL) - pte = pmap_expand_kmap(pa, 0); + npg = atop(sz); + curpa = pa; + while (npg-- != 0) { + if ((pte = pmap_pte(pmap_kernel(), curpa)) == NULL) + pte = pmap_expand_kmap(curpa, 0); - *pte = npte | pa; - pa += PAGE_SIZE; + *pte = npte | curpa; + curpa += PAGE_SIZE; pmap_kernel()->pm_stats.resident_count++; pmap_kernel()->pm_stats.wired_count++; } + + if (may_use_batc) { + sz = round_batc(pa + sz) - trunc_batc(pa); + pa = trunc_batc(pa); + + batc = BATC_SO | BATC_V; + if ((prot & VM_PROT_WRITE) == 0) + batc |= BATC_PROT; + if (cmode & CACHE_INH) + batc |= BATC_INH; + if (cmode & CACHE_WT) + batc |= BATC_WT; + batc |= BATC_GLOBAL; /* XXX 88110 SP */ + + for (; sz != 0; sz -= BATC_BLKBYTES, pa += BATC_BLKBYTES) { + /* check if an existing BATC covers this area */ + for (batcno = 0; batcno < BATC_MAX; batcno++) { + if ((global_dbatc[batcno] & BATC_V) == 0) + continue; + curpa = (global_dbatc[batcno] << + (BATC_BLKSHIFT - BATC_PSHIFT)) & + ~BATC_BLKMASK; + if (curpa == pa) + break; + } + + /* + * If there is a BATC covering this range, reuse it. + * We assume all BATC-possible mappings will use the + * same protection and cacheability settings. + */ + if (batcno != BATC_MAX) + continue; + + /* create a new DBATC if possible */ + for (batcno = BATC_MAX; batcno != 0; batcno--) { + if (global_dbatc[batcno - 1] & BATC_V) + continue; + global_dbatc[batcno - 1] = batc | + ((pa >> BATC_BLKSHIFT) << BATC_PSHIFT) | + ((pa >> BATC_BLKSHIFT) << BATC_VSHIFT); + break; + } + } + } } /* @@ -666,13 +791,14 @@ pmap_bootstrap(paddr_t s_rom, paddr_t e_rom) if (e_rom != s_rom) { s_firmware = s_rom; l_firmware = e_rom - s_rom; - pmap_map(s_firmware, l_firmware, UVM_PROT_RW, CACHE_INH); + pmap_map(s_firmware, l_firmware, UVM_PROT_RW, CACHE_INH, FALSE); } for (ptable = pmap_table_build(); ptable->size != (vsize_t)-1; ptable++) if (ptable->size != 0) pmap_map(ptable->start, ptable->size, - ptable->prot, ptable->cacheability); + ptable->prot, ptable->cacheability, + ptable->may_use_batc); /* * Adjust cache settings according to the hardware we are running on. |