Module Name: src Committed By: matt Date: Mon Feb 13 18:20:26 UTC 2012
Modified Files: src/sys/arch/mips/include [matt-nb5-mips64]: cpu.h locore.h src/sys/arch/mips/mips [matt-nb5-mips64]: bus_dma.c mem.c mips_machdep.c pmap.c pmap_segtab.c vm_machdep.c Log Message: Add mm_md_direct_mapped_virt (inverse of mm_md_direct_mapped_phys). Add a third argument, vsize_t *, which, if not NULL, returns the amount of virtual space left in that direct mapped segment. Get rid most of the individual direct_mapped assert and use the above routines instead. Improve kernel core dump code. To generate a diff of this commit: cvs rdiff -u -r1.90.16.42 -r1.90.16.43 src/sys/arch/mips/include/cpu.h cvs rdiff -u -r1.78.36.1.2.33 -r1.78.36.1.2.34 \ src/sys/arch/mips/include/locore.h cvs rdiff -u -r1.22.16.21 -r1.22.16.22 src/sys/arch/mips/mips/bus_dma.c cvs rdiff -u -r1.35.38.10 -r1.35.38.11 src/sys/arch/mips/mips/mem.c cvs rdiff -u -r1.205.4.1.2.1.2.64 -r1.205.4.1.2.1.2.65 \ src/sys/arch/mips/mips/mips_machdep.c cvs rdiff -u -r1.179.16.40 -r1.179.16.41 src/sys/arch/mips/mips/pmap.c cvs rdiff -u -r1.1.2.13 -r1.1.2.14 src/sys/arch/mips/mips/pmap_segtab.c cvs rdiff -u -r1.121.6.1.2.26 -r1.121.6.1.2.27 \ src/sys/arch/mips/mips/vm_machdep.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/mips/include/cpu.h diff -u src/sys/arch/mips/include/cpu.h:1.90.16.42 src/sys/arch/mips/include/cpu.h:1.90.16.43 --- src/sys/arch/mips/include/cpu.h:1.90.16.42 Mon Feb 13 08:13:41 2012 +++ src/sys/arch/mips/include/cpu.h Mon Feb 13 18:20:25 2012 @@ -637,7 +637,8 @@ void fpusave_cpu(struct cpu_info *); void dumpsys(void); int savectx(struct pcb *); void cpu_identify(device_t, const char *); -bool mm_md_direct_mapped_phys(paddr_t, vaddr_t *); +bool mm_md_direct_mapped_phys(paddr_t, vaddr_t *, vsize_t *); +bool mm_md_direct_mapped_virt(vaddr_t, paddr_t *, vsize_t *); /* locore*.S */ int badaddr(void *, size_t); Index: src/sys/arch/mips/include/locore.h diff -u src/sys/arch/mips/include/locore.h:1.78.36.1.2.33 src/sys/arch/mips/include/locore.h:1.78.36.1.2.34 --- src/sys/arch/mips/include/locore.h:1.78.36.1.2.33 Mon Feb 13 08:13:41 2012 +++ src/sys/arch/mips/include/locore.h Mon Feb 13 18:20:25 2012 @@ -32,6 +32,8 @@ #include "opt_cputype.h" #endif +#include <sys/kcore.h> + #include <mips/mutex.h> #include <mips/cpuregs.h> #include <mips/reg.h> @@ -417,6 +419,19 @@ void mips_page_physload(vaddr_t, vaddr_t const struct phys_ram_seg *, size_t, const struct mips_vmfreelist *, size_t); +paddr_t kvtophys(vaddr_t); + +extern struct phys_ram_seg mem_clusters[]; +extern u_int mem_cluster_cnt; + +#ifndef _LP64 +/* + * Helper routines for kernel coredumps. + */ +bool mips_kcore_window_vtophys(vaddr_t, paddr_t *); +vaddr_t mips_kcore_window_map(paddr_t, vsize_t *); +#endif + /* * CPU identification, from PRID register. Index: src/sys/arch/mips/mips/bus_dma.c diff -u src/sys/arch/mips/mips/bus_dma.c:1.22.16.21 src/sys/arch/mips/mips/bus_dma.c:1.22.16.22 --- src/sys/arch/mips/mips/bus_dma.c:1.22.16.21 Tue Dec 6 17:37:55 2011 +++ src/sys/arch/mips/mips/bus_dma.c Mon Feb 13 18:20:25 2012 @@ -1009,18 +1009,22 @@ _bus_dmamem_map(bus_dma_tag_t t, bus_dma return 0; } #else - if ((nsegs == 1) && (segs[0].ds_addr < MIPS_PHYS_MASK)) { - if (((mips_options.mips_cpu_flags & CPU_MIPS_D_CACHE_COHERENT) == 0) - && (flags & BUS_DMA_COHERENT)) + if (nsegs == 1) { + vsize_t vs; + if (!(mips_options.mips_cpu_flags & CPU_MIPS_D_CACHE_COHERENT) + && segs[0].ds_addr < MIPS_PHYS_MASK + && segs[0].ds_addr + segs[0].ds_len <= MIPS_PHYS_MASK + 1 + && (flags & BUS_DMA_COHERENT)) { *kvap = (void *)MIPS_PHYS_TO_KSEG1(segs[0].ds_addr); -#ifdef ENABLE_MIPS_KSEGX - else if (mips_ksegx_start < segs[0].ds_addr - && segs[0].ds_addr < mips_ksegx_start + VM_KSEGX_SIZE) - *kvap = (void *)(vaddr_t)(VM_KSEGX_ADDRESS + segs[0].ds_addr); -#endif - else - *kvap = (void *)MIPS_PHYS_TO_KSEG0(segs[0].ds_addr); - return (0); + return (0); + } + if (((mips_options.mips_cpu_flags & CPU_MIPS_D_CACHE_COHERENT) + || (flags & BUS_DMA_COHERENT) == 0) + && mm_md_direct_mapped_phys(segs[0].ds_addr, &va, &vs) + && segs[0].ds_len <= vs) { + *kvap = (void *)va; + return (0); + } } #endif /* _LP64 */ @@ -1068,17 +1072,9 @@ _bus_dmamem_unmap(bus_dma_tag_t t, void * Nothing to do if we mapped it with KSEG0 or KSEG1 (i.e. * not in KSEG2 or XKSEG). */ - if (MIPS_KSEG0_P(kva) || MIPS_KSEG1_P(kva)) - return; -#ifdef ENABLE_MIPS_KSEGX - if (VM_KSEGX_ADDRESS <= (vaddr_t)kva - && (vaddr_t)kva < VM_KSEGX_ADDRESS + VM_KSEGX_SIZE) + if (mm_md_direct_mapped_virt((vaddr_t)kva, NULL, NULL) + || MIPS_KSEG1_P(kva)) return; -#endif -#ifdef _LP64 - if (MIPS_XKPHYS_P((vaddr_t)kva)) - return; -#endif size = round_page(size); pmap_remove(pmap_kernel(), (vaddr_t)kva, (vaddr_t)kva + size); Index: src/sys/arch/mips/mips/mem.c diff -u src/sys/arch/mips/mips/mem.c:1.35.38.10 src/sys/arch/mips/mips/mem.c:1.35.38.11 --- src/sys/arch/mips/mips/mem.c:1.35.38.10 Tue Jan 10 18:36:58 2012 +++ src/sys/arch/mips/mips/mem.c Mon Feb 13 18:20:25 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: mem.c,v 1.35.38.10 2012/01/10 18:36:58 matt Exp $ */ +/* mem.c,v 1.35.38.10 2012/01/10 18:36:58 matt Exp */ /* * Copyright (c) 1988 University of Utah. @@ -44,7 +44,7 @@ #include "opt_mips_cache.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mem.c,v 1.35.38.10 2012/01/10 18:36:58 matt Exp $"); +__KERNEL_RCSID(0, "mem.c,v 1.35.38.10 2012/01/10 18:36:58 matt Exp"); #include <sys/param.h> #include <sys/conf.h> @@ -85,8 +85,10 @@ const struct cdevsw mem_ultrix_cdevsw = int mmrw(dev_t dev, struct uio *uio, int flags) { - vaddr_t v; - int c; + paddr_t pa; + vsize_t vs; + vaddr_t va; + size_t c; struct iovec *iov; int error = 0; @@ -102,79 +104,70 @@ mmrw(dev_t dev, struct uio *uio, int fla switch (minor(dev)) { case DEV_MEM: - v = uio->uio_offset; + pa = uio->uio_offset; c = iov->iov_len; /* * XXX Broken; assumes contiguous physical memory. */ -#ifdef _LP64 - if (v + c > ctob(physmem)) + if (!mm_md_direct_mapped_phys(pa, &va, &vs)) + return EFAULT; + if (vs < c) + c = vs; + if (pa + c > ctob(physmem)) return (EFAULT); - v = MIPS_PHYS_TO_XKPHYS_CACHED(v); -#else - if (MIPS_KSEG0_P(v + c - 1)) { - v = MIPS_PHYS_TO_KSEG0(v); -#ifdef ENABLE_MIPS_KSEGX - } else if (mips_ksegx_start <= v - && v + c <= mips_ksegx_start + VM_KSEGX_SIZE) { - v += VM_KSEGX_ADDRESS - mips_ksegx_start; -#endif - } else - return (EFAULT); -#endif - error = uiomove((void *)v, c, uio); + + error = uiomove((void *)va, c, uio); #if defined(MIPS3_PLUS) if (MIPS_CACHE_VIRTUAL_ALIAS) - mips_dcache_wbinv_range(v, c); + mips_dcache_wbinv_range(va, c); #endif continue; case DEV_KMEM: - v = uio->uio_offset; + va = uio->uio_offset; c = min(iov->iov_len, MAXPHYS); #ifdef _LP64 - if (v < MIPS_XKPHYS_START) { - return (EFAULT); - } else if (MIPS_XKPHYS_P(v) - && v > MIPS_PHYS_TO_XKPHYS_CACHED(mips_avail_end + - mips_round_page(MSGBUFSIZE) - c)) { + if (va < MIPS_XKPHYS_START) { return (EFAULT); - } else if (MIPS_XKSEG_P(v) + } else if (mm_md_direct_mapped_virt(va, &pa, &vs)) { + if (c > vs) + c = vs; + if (pa > mips_avail_end + + mips_round_page(MSGBUFSIZE) - c)) { + return (EFAULT); + } else if (MIPS_XKSEG_P(va) && v < MIPS_KSEG0_START - && !uvm_kernacc((void *)v, c, + && !uvm_kernacc((void *)va, c, uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) { return (EFAULT); - } else if (MIPS_KSEG1_P(v) || MIPS_KSEG2_P(v)) { + } else if (MIPS_KSEG1_P(va) || MIPS_KSEG2_P(va)) { return (EFAULT); } #else - if (v < MIPS_KSEG0_START) + if (va < MIPS_KSEG0_START) return (EFAULT); - if (MIPS_KSEG0_P(v + c - 1)) { + if (mm_md_direct_mapped_virt(va, &pa, &vs)) { + if (c > vs) + c = vs; /* * If all of memory is in KSEG0, make sure we * don't go beyond its limit. (mips_avail_end * may be beyond the end of KSEG0). */ - if (MIPS_KSEG0_TO_PHYS(v) >= mips_avail_end + if (pa >= mips_avail_end + mips_round_page(MSGBUFSIZE) - c) return (EFAULT); -#ifdef ENABLE_MIPS_KSEGX - } else if (VM_KSEGX_ADDRESS <= v - && v + c <= VM_KSEGX_ADDRESS + VM_KSEGX_SIZE) { - /* nothing */ -#endif - } else if (v < MIPS_KSEG2_START - || !uvm_kernacc((void *)v, c, + } else if (va < MIPS_KSEG2_START + || !uvm_kernacc((void *)va, c, uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) return (EFAULT); #endif - error = uiomove((void *)v, c, uio); + error = uiomove((void *)va, c, uio); #if defined(MIPS3_PLUS) if (MIPS_CACHE_VIRTUAL_ALIAS) - mips_dcache_wbinv_range(v, c); + mips_dcache_wbinv_range(va, c); #endif continue; Index: src/sys/arch/mips/mips/mips_machdep.c diff -u src/sys/arch/mips/mips/mips_machdep.c:1.205.4.1.2.1.2.64 src/sys/arch/mips/mips/mips_machdep.c:1.205.4.1.2.1.2.65 --- src/sys/arch/mips/mips/mips_machdep.c:1.205.4.1.2.1.2.64 Mon Feb 13 08:13:42 2012 +++ src/sys/arch/mips/mips/mips_machdep.c Mon Feb 13 18:20:25 2012 @@ -259,6 +259,8 @@ extern const mips_locore_jumpvec_t mips6 void std_splsw_test(void); #endif +static void mips_kcore_window_unmap(void); + CTASSERT(CPU_ARCH_MIPS64R2 / CPU_ARCH_MIPS64 == CPU_ARCH_MIPS32R2 / CPU_ARCH_MIPS32); mips_locore_jumpvec_t mips_locore_jumpvec; @@ -1766,22 +1768,13 @@ SYSCTL_SETUP(sysctl_machdep_setup, "sysc } /* - * These are imported from platform-specific code. - * XXX Should be declared in a header file. - */ -extern phys_ram_seg_t mem_clusters[]; -extern int mem_cluster_cnt; - -/* * These variables are needed by /sbin/savecore. */ -u_int32_t dumpmag = 0x8fca0101; /* magic number */ +uint32_t dumpmag = 0x8fca0101; /* magic number */ int dumpsize = 0; /* pages */ -long dumplo = 0; /* blocks */ +long dumplo = -1; /* blocks */ -#if 0 struct pcb dumppcb; -#endif /* * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers. @@ -1789,11 +1782,13 @@ struct pcb dumppcb; int cpu_dumpsize(void) { - int size; + size_t size = 0; + + size += ALIGN(sizeof(kcore_seg_t)); + size += ALIGN(sizeof(cpu_kcore_hdr_t)); + size += ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t)); - size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)) + - ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t)); - if (roundup(size, dbtob(1)) != dbtob(1)) + if (size > dbtob(1)) return (-1); return (1); @@ -1805,11 +1800,16 @@ cpu_dumpsize(void) u_long cpu_dump_mempagecnt(void) { - u_long i, n; + u_long n; n = 0; - for (i = 0; i < mem_cluster_cnt; i++) + for (u_int i = 0; i < mem_cluster_cnt; i++) { n += atop(mem_clusters[i].size); + if (n >= atop(INT32_MAX)) { + n = atop(INT32_MAX); + break; + } + } return (n); } @@ -1820,11 +1820,14 @@ int cpu_dump(void) { int (*dump)(dev_t, daddr_t, void *, size_t); - char buf[dbtob(1)]; + uint64_t buf64[dbtob(1)/sizeof(uint64_t)]; + uint8_t * const buf = (uint8_t *)buf64; + uint8_t *bp = buf; kcore_seg_t *segp; cpu_kcore_hdr_t *cpuhdrp; phys_ram_seg_t *memsegp; const struct bdevsw *bdev; + const size_t blocksize = dbtob(1); int i; bdev = bdevsw_lookup(dumpdev); @@ -1834,16 +1837,15 @@ cpu_dump(void) dump = bdev->d_dump; memset(buf, 0, sizeof buf); - segp = (kcore_seg_t *)buf; - cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp))]; - memsegp = (phys_ram_seg_t *)&buf[ ALIGN(sizeof(*segp)) + - ALIGN(sizeof(*cpuhdrp))]; + segp = (kcore_seg_t *)bp; bp += ALIGN(sizeof(*segp)); + cpuhdrp = (cpu_kcore_hdr_t *)bp; bp += ALIGN(sizeof(*cpuhdrp)); + memsegp = (phys_ram_seg_t *)bp; /* * Generate a segment header. */ CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU); - segp->c_size = dbtob(1) - ALIGN(sizeof(*segp)); + segp->c_size = blocksize - ALIGN(sizeof(*segp)); /* * Add the machine-dependent header info. @@ -1879,7 +1881,7 @@ cpu_dump(void) memsegp[i].size = mem_clusters[i].size; } - return (dump(dumpdev, dumplo, (void *)buf, dbtob(1))); + return dump(dumpdev, dumplo, buf, blocksize); } /* @@ -1905,7 +1907,7 @@ cpu_dumpconf(void) if (bdev->d_psize == NULL) goto bad; nblks = (*bdev->d_psize)(dumpdev); - if (nblks <= ctod(1)) + if (nblks < 0) goto bad; dumpblks = cpu_dumpsize(); @@ -1914,7 +1916,7 @@ cpu_dumpconf(void) dumpblks += ctod(cpu_dump_mempagecnt()); /* If dump won't fit (incl. room for possible label), punt. */ - if (dumpblks > (nblks - ctod(1))) + if (nblks <= dumpblks) goto bad; /* Put dump at end of partition */ @@ -1931,23 +1933,19 @@ cpu_dumpconf(void) /* * Dump the kernel's image to the swap partition. */ -#define BYTES_PER_DUMP PAGE_SIZE +#define BYTES_PER_DUMP MAXPHYS void dumpsys(void) { - u_long totalbytesleft, bytes, i, n, memcl; - u_long maddr; - int psize; + psize_t totalbytesleft; daddr_t blkno; const struct bdevsw *bdev; int (*dump)(dev_t, daddr_t, void *, size_t); int error; -#if 0 /* Save registers. */ savectx(&dumppcb); -#endif if (dumpdev == NODEV) return; @@ -1969,9 +1967,9 @@ dumpsys(void) printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev), minor(dumpdev), dumplo); - psize = (*bdev->d_psize)(dumpdev); + int nblks = (*bdev->d_psize)(dumpdev); printf("dump "); - if (psize == -1) { + if (nblks == -1) { printf("area unavailable\n"); return; } @@ -1986,29 +1984,29 @@ dumpsys(void) dump = bdev->d_dump; error = 0; - for (memcl = 0; memcl < mem_cluster_cnt; memcl++) { - maddr = mem_clusters[memcl].start; - bytes = mem_clusters[memcl].size; - - for (i = 0; i < bytes; i += n, totalbytesleft -= n) { - void *maddr_va; + int32_t meg = 1024*1024; + for (size_t memcl = 0; memcl < mem_cluster_cnt; memcl++) { + paddr_t maddr = mem_clusters[memcl].start; + psize_t msize = mem_clusters[memcl].size; + vsize_t n = 0; + + for (psize_t i = 0; + i < msize; + i += n, totalbytesleft -= n, meg -= n) { + vaddr_t maddr_va; /* Print out how many MBs we have left to go. */ - if ((totalbytesleft % (1024*1024)) == 0) - printf_nolog("%ld ", - totalbytesleft / (1024 * 1024)); + if (meg <= 0) { + printf_nolog("%u ", + (u_int)(totalbytesleft >> 20)); + meg += 1024*1024; + } /* Limit size for next transfer. */ - n = bytes - i; - if (n > BYTES_PER_DUMP) - n = BYTES_PER_DUMP; + n = MIN(BYTES_PER_DUMP, msize - i); -#ifdef _LP64 - maddr_va = (void *)MIPS_PHYS_TO_XKPHYS_CACHED(maddr); -#else - maddr_va = (void *)MIPS_PHYS_TO_KSEG0(maddr); -#endif - error = (*dump)(dumpdev, blkno, maddr_va, n); + maddr_va = mips_kcore_window_map(maddr, &n); + error = (*dump)(dumpdev, blkno, (void*)maddr_va, n); if (error) goto err; maddr += n; @@ -2017,6 +2015,7 @@ dumpsys(void) /* XXX should look for keystrokes, to cancel. */ } } + mips_kcore_window_unmap(); err: switch (error) { @@ -2053,6 +2052,98 @@ dumpsys(void) delay(5000000); /* 5 seconds */ } +#ifdef MIPS3_PLUS +static struct mips_kcore_window_info { + struct tlbmask mkwi_tlb; + int mkwi_tlb_slot; +} mips_kcore_window_info = { + .mkwi_tlb = { + .tlb_hi = 1024*1024*1024, + .tlb_mask = MIPS3_PG_SIZE_256M, + }, + .mkwi_tlb_slot = -1, +}; +#endif + +bool +mips_kcore_window_vtophys(vaddr_t va, paddr_t *pap) +{ +#ifdef MIPS3_PLUS + struct mips_kcore_window_info * const mkwi = &mips_kcore_window_info; + const vaddr_t tlb_va = mkwi->mkwi_tlb.tlb_hi & -PAGE_SIZE; + psize_t tlb_size = MIPS3_PG_SIZE_MASK_TO_SIZE(mkwi->mkwi_tlb.tlb_mask); + if (mips_pg_v(mkwi->mkwi_tlb.tlb_lo0) + && tlb_va <= va && va < tlb_va + 2 * tlb_size) { + *pap = va - tlb_va + + mips_tlbpfn_to_paddr(mkwi->mkwi_tlb.tlb_lo0); + return true; + } +#endif + return false; +} + +vaddr_t +mips_kcore_window_map(paddr_t pa, vsize_t *vsp) +{ + vaddr_t va; + vsize_t vs; + if (mm_md_direct_mapped_phys(pa, &va, &vs)) { +#ifndef _LP64 + /* + * Make sure the length we want to mapped doesn't cross the + * direct-mapped boundary. + */ + if (*vsp > vs) + *vsp = vs; +#endif + return va; + } +#if defined(MIPS3_PLUS) && !defined(_LP64) + KASSERT(MIPS_HAS_R4K_MMU); + struct mips_kcore_window_info * const mkwi = &mips_kcore_window_info; + paddr_t tlb_pa = mips_tlbpfn_to_paddr(mkwi->mkwi_tlb.tlb_lo0); + psize_t tlb_size = MIPS3_PG_SIZE_MASK_TO_SIZE(mkwi->mkwi_tlb.tlb_mask); + if (!mips_pg_v(mkwi->mkwi_tlb.tlb_lo0) + || pa < tlb_pa + || tlb_pa + 2 * tlb_size <= pa) { + tlb_pa = pa & (2 * tlb_size - 1); + mkwi->mkwi_tlb.tlb_lo0 = mips_paddr_to_tlbpfn(tlb_pa) + | MIPS3_PG_CACHED | MIPS3_PG_V | MIPS3_PG_G; + mkwi->mkwi_tlb.tlb_lo0 = mkwi->mkwi_tlb.tlb_lo1 + + mips_paddr_to_tlbpfn(tlb_size); + + if (mkwi->mkwi_tlb_slot < 0) { + mkwi->mkwi_tlb_slot = pmap_tlb0_info.ti_wired++; + mips3_cp0_wired_write(pmap_tlb0_info.ti_wired); + } + tlb_write_indexed(mkwi->mkwi_tlb_slot, &mkwi->mkwi_tlb); + } + if (*vsp + pa - tlb_pa > 2 * tlb_size) + *vsp = tlb_pa + 2 * tlb_size - pa; + return (mkwi->mkwi_tlb.tlb_hi & -PAGE_SIZE) + pa - tlb_pa; +#else + panic("%s: failed to map non-KSEG0 memory", __func__); +#endif /* MIPS3_PLUS && !_LP64 */ +} + +void +mips_kcore_window_unmap(void) +{ +#if defined(MIPS3_PLUS) && !defined(_LP64) + struct mips_kcore_window_info * const mkwi = &mips_kcore_window_info; + if (mkwi->mkwi_tlb_slot >= 0) { + struct tlbmask tlb; + mkwi->mkwi_tlb.tlb_lo0 = 0; + mkwi->mkwi_tlb.tlb_lo1 = 0; + tlb.tlb_hi = mkwi->mkwi_tlb_slot << (PAGE_SHIFT | 1); + tlb.tlb_lo0 = 0; + tlb.tlb_lo1 = 0; + tlb.tlb_mask = 0; + tlb_write_indexed(mkwi->mkwi_tlb_slot, &mkwi->mkwi_tlb); + } +#endif /* MIPS3_PLUS && !_LP64 */ +} + void mips_init_msgbuf(void) { @@ -2456,23 +2547,64 @@ mips_watchpoint_init(void) #endif bool -mm_md_direct_mapped_phys(paddr_t pa, vaddr_t *vap) +mm_md_direct_mapped_phys(paddr_t pa, vaddr_t *vap, vsize_t *vsp) { #ifdef _LP64 - *vap = MIPS_PHYS_TO_XKPHYS_CACHED(pa); + if (vap != NULL) + *vap = MIPS_PHYS_TO_XKPHYS_CACHED(pa); + if (vsp != NULL) + *vsp = MIPS_XKPHYS_TO_PHYS(MIPS_XKPHYS_MASK) - pa + 1; return true; #else #ifdef ENABLE_MIPS_KSEGX if (mips_ksegx_start <= pa && pa < mips_ksegx_start + VM_KSEGX_SIZE) { - *vap = VM_KSEGX_ADDRESS + pa - mips_ksegx_start; + if (vap != NULL) + *vap = VM_KSEGX_ADDRESS + pa - mips_ksegx_start; + if (vsp != NULL) + *vsp = mips_ksegx_start + VM_KSEGX_SIZE - pa; return true; } #endif if (pa <= MIPS_PHYS_MASK) { - *vap = MIPS_PHYS_TO_KSEG0(pa); + if (vap != NULL) + *vap = MIPS_PHYS_TO_KSEG0(pa); + if (vsp != NULL) + *vsp = MIPS_PHYS_MASK - pa + 1; return true; } return false; #endif } +bool +mm_md_direct_mapped_virt(vaddr_t va, paddr_t *pap, vsize_t *vsp) +{ +#ifdef _LP64 + if (MIPS_XKPHYS_P(va)) { + const paddr_t pa = MIPS_XKPHYS_TO_PHYS(va); + if (pap != NULL) + *pap = pa; + if (vsp != NULL) + *vsp = MIPS_XKPHYS_TO_PHYS(MIPS_XKPHYS_MASK) - pa + 1; + return true; + } +#endif +#ifdef ENABLE_MIPS_KSEGX + if (VM_KSEGX_ADDRESS <= va && va < VM_KSEGX_ADDRESS + VM_KSEGX_SIZE) { + const paddr_t pa = mips_ksegx_start + va - VM_KSEGX_ADDRESS; + if (pap != NULL) + *pap = pa; + if (vsp != NULL) + *vsp = VM_KSEGX_ADDRESS + VM_KSEGX_SIZE - va; + return true; + } +#endif + if (MIPS_KSEG0_P(va)) { + if (pap != NULL) + *pap = MIPS_KSEG0_TO_PHYS(va); + if (vsp != NULL) + *vsp = MIPS_KSEG1_START - va; + return true; + } + return false; +} Index: src/sys/arch/mips/mips/pmap.c diff -u src/sys/arch/mips/mips/pmap.c:1.179.16.40 src/sys/arch/mips/mips/pmap.c:1.179.16.41 --- src/sys/arch/mips/mips/pmap.c:1.179.16.40 Sun Feb 12 07:48:37 2012 +++ src/sys/arch/mips/mips/pmap.c Mon Feb 13 18:20:26 2012 @@ -364,18 +364,9 @@ pmap_map_ephemeral_page(struct vm_page * const paddr_t pa = VM_PAGE_TO_PHYS(pg); struct vm_page_md * const md = VM_PAGE_TO_MD(pg); pv_entry_t pv = &md->pvh_first; - -#ifdef _LP64 - vaddr_t va = MIPS_PHYS_TO_XKPHYS_CACHED(pa); -#else vaddr_t va; - if (pa <= MIPS_PHYS_MASK) { - va = MIPS_PHYS_TO_KSEG0(pa); -#ifdef ENABLE_MIPS_KSEGX - } else if (mips_ksegx_start <= pa && pa < mips_ksegx_start + VM_KSEGX_SIZE) { - va = VM_KSEGX_ADDRESS + pa - mips_ksegx_start; -#endif - } else { + + if (!mm_md_direct_mapped_phys(pa, &va, NULL)) { KASSERT(pmap_initialized); /* * Make sure to use a congruent mapping to the last mapped @@ -389,7 +380,6 @@ pmap_map_ephemeral_page(struct vm_page * *old_pt_entry_p = *kvtopte(va); pmap_kenter_pa(va, pa, prot); } -#endif /* _LP64 */ if (MIPS_CACHE_VIRTUAL_ALIAS) { /* * If we are forced to use an incompatible alias, flush the @@ -1342,11 +1332,7 @@ pmap_page_cache(struct vm_page *pg, bool uint32_t pt_entry; KASSERT(pmap != NULL); - KASSERT(!MIPS_KSEG0_P(va)); - KASSERT(!MIPS_KSEG1_P(va)); -#ifdef _LP64 - KASSERT(!MIPS_XKPHYS_P(va)); -#endif + KASSERT(!mm_md_direct_mapped_virt(va, NULL, NULL)); if (pmap == pmap_kernel()) { /* * Change entries in kernel pmap. @@ -1829,22 +1815,8 @@ pmap_extract(pmap_t pmap, vaddr_t va, pa printf("pmap_extract(%p, %#"PRIxVADDR") -> ", pmap, va); #endif if (pmap == pmap_kernel()) { - if (MIPS_KSEG0_P(va)) { - pa = MIPS_KSEG0_TO_PHYS(va); + if (mm_md_direct_mapped_virt(va, &pa, NULL)) goto done; - } -#ifdef _LP64 - if (MIPS_XKPHYS_P(va)) { - pa = MIPS_XKPHYS_TO_PHYS(va); - goto done; - } -#elif defined(ENABLE_MIPS_KSEGX) - if (VM_KSEGX_ADDRESS <= va - && va < VM_KSEGX_ADDRESS + VM_KSEGX_SIZE) { - pa = mips_ksegx_start + va - VM_KSEGX_ADDRESS; - goto done; - } -#endif #ifdef DIAGNOSTIC if (MIPS_KSEG1_P(va)) panic("pmap_extract: kseg1 address %#"PRIxVADDR"", va); @@ -2125,11 +2097,7 @@ pmap_check_pvlist(struct vm_page_md *md) pt_entry_t pv = &md->pvh_first; if (pv->pv_pmap != NULL) { for (; pv != NULL; pv = pv->pv_next) { - KASSERT(!MIPS_KSEG0_P(pv->pv_va)); - KASSERT(!MIPS_KSEG1_P(pv->pv_va)); -#ifdef _LP64 - KASSERT(!MIPS_XKPHYS_P(pv->pv_va)); -#endif + KASSERT(!mm_md_direct_mapped_virt(pv->pv_va, NULL, NULL)); } pv = &md->pvh_first; } @@ -2148,11 +2116,7 @@ pmap_enter_pv(pmap_t pmap, vaddr_t va, s int16_t gen; KASSERT(kpreempt_disabled()); - KASSERT(!MIPS_KSEG0_P(va)); - KASSERT(!MIPS_KSEG1_P(va)); -#ifdef _LP64 - KASSERT(!MIPS_XKPHYS_P(va)); -#endif + KASSERT(!mm_md_direct_mapped_virt(va, NULL, NULL)); apv = NULL; pv = &md->pvh_first; @@ -2534,20 +2498,8 @@ pmap_pv_page_free(struct pool *pp, void vaddr_t va = (vaddr_t)v; paddr_t pa; -#ifdef _LP64 - KASSERT(MIPS_XKPHYS_P(va)); - pa = MIPS_XKPHYS_TO_PHYS(va); -#else -#ifdef ENABLE_MIPS_KSEGX - if (VM_KSEGX_ADDRESS <= va && va <= VM_KSEGX_ADDRESS + VM_KSEGX_SIZE) { - pa = mips_ksegx_start + va - VM_KSEGX_ADDRESS; - } else -#endif - { - KASSERT(MIPS_KSEG0_P(va)); - pa = MIPS_KSEG0_TO_PHYS(va); - } -#endif + bool ok = mm_md_direct_mapped_virt(va, &pa, NULL); + KASSERT(ok); #ifdef MIPS3_PLUS if (MIPS_CACHE_VIRTUAL_ALIAS) mips_dcache_inv_range(va, PAGE_SIZE); @@ -2636,19 +2588,10 @@ mips_pmap_map_poolpage(paddr_t pa) #ifdef _LP64 KASSERT(mips_options.mips3_xkphys_cached); - va = MIPS_PHYS_TO_XKPHYS_CACHED(pa); -#else -#ifdef ENABLE_MIPS_KSEGX - if (pa >= mips_ksegx_start && pa < mips_ksegx_start + VM_KSEGX_SIZE) { - va = VM_KSEGX_ADDRESS + pa - mips_ksegx_start; - } else -#endif - if (pa > MIPS_PHYS_MASK) - panic("mips_pmap_map_poolpage: " - "pa #%"PRIxPADDR" can not be mapped into KSEG0", pa); - else - va = MIPS_PHYS_TO_KSEG0(pa); #endif + if (!mm_md_direct_mapped_phys(pa, &va, NULL)) + panic("%s: pa #%"PRIxPADDR" can not be direct mapped", + __func__, pa); #if !defined(_LP64) if (MIPS_CACHE_VIRTUAL_ALIAS) { /* @@ -2672,20 +2615,8 @@ paddr_t mips_pmap_unmap_poolpage(vaddr_t va) { paddr_t pa; -#if defined(_LP64) - KASSERT(MIPS_XKPHYS_P(va)); - pa = MIPS_XKPHYS_TO_PHYS(va); -#else -#ifdef ENABLE_MIPS_KSEGX - if (VM_KSEGX_ADDRESS <= va && va < VM_KSEGX_ADDRESS + VM_KSEGX_SIZE) { - pa = mips_ksegx_start + va - VM_KSEGX_ADDRESS; - } else -#endif - { - KASSERT(MIPS_KSEG0_P(va)); - pa = MIPS_KSEG0_TO_PHYS(va); - } -#endif + bool ok = mm_md_direct_mapped_virt(va, &pa, NULL); + KASSERT(ok); struct vm_page *pg = PHYS_TO_VM_PAGE(pa); KASSERT(pg); pmap_clear_mdpage_attributes(VM_PAGE_TO_MD(pg), PG_MD_POOLPAGE); @@ -2699,9 +2630,3 @@ mips_pmap_unmap_poolpage(vaddr_t va) #endif return pa; } - - - -/******************** page table page management ********************/ - -/* TO BE DONE */ Index: src/sys/arch/mips/mips/pmap_segtab.c diff -u src/sys/arch/mips/mips/pmap_segtab.c:1.1.2.13 src/sys/arch/mips/mips/pmap_segtab.c:1.1.2.14 --- src/sys/arch/mips/mips/pmap_segtab.c:1.1.2.13 Fri Feb 10 07:14:49 2012 +++ src/sys/arch/mips/mips/pmap_segtab.c Mon Feb 13 18:20:26 2012 @@ -162,10 +162,8 @@ static inline pt_entry_t * pmap_segmap(struct pmap *pmap, vaddr_t va) { union segtab *stp = pmap->pm_segtab; - KASSERT(!MIPS_KSEG0_P(va)); - KASSERT(!MIPS_KSEG1_P(va)); + KASSERT(!mm_md_direct_mapped_virt(va, NULL, NULL)); #ifdef _LP64 - KASSERT(!MIPS_XKPHYS_P(va)); stp = stp->seg_seg[(va >> XSEGSHIFT) & (NSEGPG - 1)]; if (stp == NULL) return NULL; @@ -238,9 +236,6 @@ pmap_segtab_release(union segtab *stp, u if (MIPS_CACHE_VIRTUAL_ALIAS) mips_dcache_inv_range((vaddr_t)pte, PAGE_SIZE); #endif /* MIPS3_PLUS */ -#ifdef _LP64 - KASSERT(MIPS_XKPHYS_P(pte)); -#endif paddr_t pa = mips_pmap_unmap_poolpage((vaddr_t)pte); struct vm_page *pg = PHYS_TO_VM_PAGE(pa); uvm_km_pagefree(pg); Index: src/sys/arch/mips/mips/vm_machdep.c diff -u src/sys/arch/mips/mips/vm_machdep.c:1.121.6.1.2.26 src/sys/arch/mips/mips/vm_machdep.c:1.121.6.1.2.27 --- src/sys/arch/mips/mips/vm_machdep.c:1.121.6.1.2.26 Thu Feb 9 03:35:59 2012 +++ src/sys/arch/mips/mips/vm_machdep.c Mon Feb 13 18:20:26 2012 @@ -164,16 +164,7 @@ cpu_lwp_fork(struct lwp *l1, struct lwp l2->l_md.md_utf = tf; l2->l_md.md_flags = l1->l_md.md_flags & MDP_FPUSED; - bool direct_mapped_p = MIPS_KSEG0_P(ua2); -#ifdef ENABLE_MIPS_KSEGX - if (!direct_mapped_p) - direct_mapped_p = VM_KSEGX_ADDRESS <= ua2 - && ua2 < VM_KSEGX_ADDRESS + VM_KSEGX_SIZE; -#endif -#ifdef _LP64 - direct_mapped_p = direct_mapped_p || MIPS_XKPHYS_P(ua2); -#endif - if (!direct_mapped_p) { + if (!mm_md_direct_mapped_virt(ua2, NULL, NULL)) { pt_entry_t * const pte = kvtopte(ua2); const uint32_t x = (MIPS_HAS_R4K_MMU) ? (MIPS3_PG_G | MIPS3_PG_RO | MIPS3_PG_WIRED) : MIPS1_PG_G; @@ -243,15 +234,12 @@ cpu_uarea_remap(struct lwp *l) * Grab the starting physical address of the uarea. */ va = (vaddr_t)l->l_addr; - if (MIPS_KSEG0_P(va)) - return; -#ifdef _LP64 - if (MIPS_XKPHYS_P(va)) - return; -#elif defined(ENABLE_MIPS_KSEGX) - if (VM_KSEGX_ADDRESS <= va && va < VM_KSEGX_ADDRESS + VM_KSEGX_SIZE) + + /* + * If already direct mapped, we're done! + */ + if (mm_md_direct_mapped_phys(va, NULL, NULL)) return; -#endif if (!pmap_extract(pmap_kernel(), va, &pa)) panic("%s: pmap_extract(%#"PRIxVADDR") failed", __func__, va); @@ -347,18 +335,8 @@ cpu_swapin(struct lwp *l) int i, x; vaddr_t kva = (vaddr_t) lwp_getpcb(l); -#ifdef _LP64 - if (MIPS_XKPHYS_P(kva)) + if (mm_md_direct_mapped_virt(kva, NULL, NULL)) return; -#else - if (MIPS_KSEG0_P(kva)) - return; - -#ifdef ENABLE_MIPS_KSEGX - if (VM_KSEGX_ADDRESS <= kva && kva < VM_KSEGX_ADDRESS + VM_KSEGX_SIZE) - return; -#endif -#endif /* * Cache the PTEs for the user area in the machine dependent @@ -510,21 +488,23 @@ vunmapbuf(struct buf *bp, vsize_t len) paddr_t kvtophys(vaddr_t kva) { - pt_entry_t *pte; paddr_t phys; - if (kva >= VM_MIN_KERNEL_ADDRESS) { - if (kva >= VM_MAX_KERNEL_ADDRESS) - goto overrun; - -#ifdef ENABLE_MIPS_KSEGX - if (VM_KSEGX_ADDRESS <= kva - && kva < VM_KSEGX_ADDRESS + VM_KSEGX_SIZE) { - return mips_ksegx_start + kva - VM_KSEGX_ADDRESS; - } -#endif + /* + * When we dumping memory in a crash dump, we try to use a large + * TLB entry to reduce the TLB trashing. + */ + if (__predict_false(mips_kcore_window_vtophys(kva, &phys))) + return phys; - pte = kvtopte(kva); + /* + * If the KVA is direct mapped, we're done! + */ + if (mm_md_direct_mapped_virt(kva, &phys, NULL)) + return phys; + + if (VM_MIN_KERNEL_ADDRESS <= kva && kva < VM_MAX_KERNEL_ADDRESS) { + pt_entry_t *pte = kvtopte(kva); if ((size_t) (pte - Sysmap) >= Sysmapsize) { printf("oops: Sysmap overrun, max %d index %zd\n", Sysmapsize, pte - Sysmap); @@ -536,20 +516,7 @@ kvtophys(vaddr_t kva) phys = mips_tlbpfn_to_paddr(pte->pt_entry) | (kva & PGOFSET); return phys; } - if (MIPS_KSEG1_P(kva)) - return MIPS_KSEG1_TO_PHYS(kva); - if (MIPS_KSEG0_P(kva)) - return MIPS_KSEG0_TO_PHYS(kva); -#ifdef _LP64 - if (MIPS_XKPHYS_P(kva)) - return MIPS_XKPHYS_TO_PHYS(kva); -#endif -overrun: - printf("Virtual address %#"PRIxVADDR": cannot map to physical\n", kva); -#ifdef DDB - Debugger(); - return 0; /* XXX */ -#endif - panic("kvtophys"); + panic("%s: Virtual address %#"PRIxVADDR": cannot map to physical\n", + __func__, kva); }