Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 12 Jul 2010 09:38:45 +0000 (UTC)
From:      "Jayachandran C." <jchandra@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r209930 - head/sys/mips/mips
Message-ID:  <201007120938.o6C9cjWD056585@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jchandra
Date: Mon Jul 12 09:38:44 2010
New Revision: 209930
URL: http://svn.freebsd.org/changeset/base/209930

Log:
  Merge jmallett@'s n64 work into HEAD.
  
  Merge changes for initial n64 support in pmap.c. Use direct mapped (XKPHYS)
  access for a lot of operations that earlier needed temporary mapping. Add
  support for using XKSEG for kernel mappings.
  
  Reviewed by:	imp
  Obtained from:	jmallett (http://svn.freebsd.org/base/user/jmallett/octeon)

Modified:
  head/sys/mips/mips/pmap.c

Modified: head/sys/mips/mips/pmap.c
==============================================================================
--- head/sys/mips/mips/pmap.c	Mon Jul 12 07:42:42 2010	(r209929)
+++ head/sys/mips/mips/pmap.c	Mon Jul 12 09:38:44 2010	(r209930)
@@ -128,7 +128,11 @@ __FBSDID("$FreeBSD$");
 #define	pmap_segshift(v)	(((v) >> SEGSHIFT) & (NPDEPG - 1))
 #define	segtab_pde(m, v)	((m)[pmap_segshift((v))])
 
+#if defined(__mips_n64)
+#define	NUSERPGTBLS		(NPDEPG)
+#else
 #define	NUSERPGTBLS		(pmap_segshift(VM_MAXUSER_ADDRESS))
+#endif
 #define	mips_segtrunc(va)	((va) & ~SEGOFSET)
 #define	is_kernel_pmap(x)	((x) == kernel_pmap)
 
@@ -196,6 +200,7 @@ static void pmap_ptpgzone_dtor(void *mem
 static void *pmap_ptpgzone_allocf(uma_zone_t, int, u_int8_t *, int);
 static uma_zone_t ptpgzone;
 
+#if !defined(__mips_n64)
 struct local_sysmaps {
 	vm_offset_t base;
 	uint16_t valid1, valid2;
@@ -256,6 +261,7 @@ static struct local_sysmaps sysmap_lmem[
 	tlb_invalidate_address(kernel_pmap, sysm->base + PAGE_SIZE);	\
 	sysm->valid2 = 0;						\
 	intr_restore(intr)
+#endif
 
 static inline pt_entry_t *
 pmap_segmap(pmap_t pmap, vm_offset_t va)
@@ -321,7 +327,7 @@ pmap_steal_memory(vm_size_t size)
 }
 
 /*
- *	Bootstrap the system enough to run with virtual memory.  This
+ * Bootstrap the system enough to run with virtual memory.  This
  * assumes that the phys_avail array has been initialized.
  */
 void
@@ -330,7 +336,9 @@ pmap_bootstrap(void)
 	pt_entry_t *pgtab;
 	pt_entry_t *pte;
 	int i, j;
+#if !defined(__mips_n64)
 	int memory_larger_than_512meg = 0;
+#endif
 
 	/* Sort. */
 again:
@@ -341,14 +349,11 @@ again:
 		phys_avail[i] = round_page(phys_avail[i]);
 		phys_avail[i + 1] = trunc_page(phys_avail[i + 1]);
 
-		if (phys_avail[i + 1] >= MIPS_KSEG0_LARGEST_PHYS)
-			memory_larger_than_512meg++;
 		if (i < 2)
 			continue;
 		if (phys_avail[i - 2] > phys_avail[i]) {
 			vm_paddr_t ptemp[2];
 
-
 			ptemp[0] = phys_avail[i + 0];
 			ptemp[1] = phys_avail[i + 1];
 
@@ -361,6 +366,11 @@ again:
 		}
 	}
 
+#if !defined(__mips_n64)
+	if (phys_avail[i - 1] >= MIPS_KSEG0_LARGEST_PHYS)
+		memory_larger_than_512meg = 1;
+#endif
+
 	/*
 	 * Copy the phys_avail[] array before we start stealing memory from it.
 	 */
@@ -395,7 +405,6 @@ again:
 	 */
 	kstack0 = pmap_steal_memory(KSTACK_PAGES << PAGE_SHIFT);
 
-
 	virtual_avail = VM_MIN_KERNEL_ADDRESS;
 	virtual_end = VM_MAX_KERNEL_ADDRESS;
 
@@ -419,6 +428,7 @@ again:
 		printf("pcpu is available at virtual address %p.\n", pcpup);
 #endif
 
+#if !defined(__mips_n64)
 	/*
 	 * Steal some virtual space that will not be in kernel_segmap. This
 	 * va memory space will be used to map in kernel pages that are
@@ -433,6 +443,7 @@ again:
 			sysmap_lmem[i].valid1 = sysmap_lmem[i].valid2 = 0;
 		}
 	}
+#endif
 
 	/*
 	 * Allocate segment table for the kernel
@@ -443,6 +454,7 @@ again:
 	 * Allocate second level page tables for the kernel
 	 */
 	nkpt = NKPT;
+#if !defined(__mips_n64)
 	if (memory_larger_than_512meg) {
 		/*
 		 * If we have a large memory system we CANNOT afford to hit
@@ -459,6 +471,7 @@ again:
 		 */
 		nkpt = (PAGE_SIZE / sizeof(pd_entry_t)) - (virtual_avail >> SEGSHIFT);
 	}
+#endif
 	pgtab = (pt_entry_t *)pmap_steal_memory(PAGE_SIZE * nkpt);
 
 	/*
@@ -768,12 +781,24 @@ pmap_kremove(vm_offset_t va)
  *	architectures should map the pages starting at '*virt' and
  *	update '*virt' with the first usable address after the mapped
  *	region.
+ *
+ *	Use XKPHYS for 64 bit, and KSEG0 where possible for 32 bit.
  */
+#if defined(__mips_n64)
+vm_offset_t
+pmap_map(vm_offset_t *virt, vm_offset_t start, vm_offset_t end, int prot)
+{
+	return (MIPS_PHYS_TO_XKPHYS_CACHED(start));
+}
+#else
 vm_offset_t
 pmap_map(vm_offset_t *virt, vm_offset_t start, vm_offset_t end, int prot)
 {
 	vm_offset_t va, sva;
 
+	if (end <= MIPS_KSEG0_LARGEST_PHYS)
+		return (MIPS_PHYS_TO_KSEG0(start));
+
 	va = sva = *virt;
 	while (start < end) {
 		pmap_kenter(va, start);
@@ -783,6 +808,7 @@ pmap_map(vm_offset_t *virt, vm_offset_t 
 	*virt = va;
 	return (sva);
 }
+#endif
 
 /*
  * Add a list of wired pages to the kva
@@ -2037,7 +2063,20 @@ pmap_enter_quick_locked(pmap_t pmap, vm_
 /*
  * Make a temporary mapping for a physical address.  This is only intended
  * to be used for panic dumps.
+ *
+ * Use XKPHYS for 64 bit, and KSEG0 where possible for 32 bit.
  */
+#if defined(__mips_n64)
+void *
+pmap_kenter_temporary(vm_paddr_t pa, int i)
+{
+	return ((void *)MIPS_PHYS_TO_XKPHYS_CACHED(pa));
+}
+void
+pmap_kenter_temporary_free(vm_paddr_t pa)
+{
+}
+#else
 void *
 pmap_kenter_temporary(vm_paddr_t pa, int i)
 {
@@ -2098,6 +2137,7 @@ pmap_kenter_temporary_free(vm_paddr_t pa
 		sysm->valid1 = 0;
 	}
 }
+#endif
 
 /*
  * Moved the code to Machine Independent
@@ -2203,7 +2243,21 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pm
 /*
  *	pmap_zero_page zeros the specified hardware page by mapping
  *	the page into KVM and using bzero to clear its contents.
+ *
+ * 	Use XKPHYS for 64 bit, and KSEG0 where possible for 32 bit.
  */
+#if defined (__mips_n64)
+void
+pmap_zero_page(vm_page_t m)
+{
+	vm_offset_t va;
+	vm_paddr_t phys = VM_PAGE_TO_PHYS(m);
+
+	va = MIPS_PHYS_TO_XKPHYS_CACHED(phys);
+	bzero((caddr_t)va, PAGE_SIZE);
+	mips_dcache_wbinv_range(va, PAGE_SIZE);
+}
+#else
 void
 pmap_zero_page(vm_page_t m)
 {
@@ -2225,13 +2279,25 @@ pmap_zero_page(vm_page_t m)
 		PMAP_LMEM_UNMAP();
 	}
 }
-
+#endif
 /*
  *	pmap_zero_page_area zeros the specified hardware page by mapping
  *	the page into KVM and using bzero to clear its contents.
  *
  *	off and size may not cover an area beyond a single hardware page.
  */
+#if defined (__mips_n64)
+void
+pmap_zero_page_area(vm_page_t m, int off, int size)
+{
+	vm_offset_t va;
+	vm_paddr_t phys = VM_PAGE_TO_PHYS(m);
+
+	va = MIPS_PHYS_TO_XKPHYS_CACHED(phys);
+	bzero((char *)(caddr_t)va + off, size);
+	mips_dcache_wbinv_range(va + off, size);
+}
+#else
 void
 pmap_zero_page_area(vm_page_t m, int off, int size)
 {
@@ -2252,7 +2318,20 @@ pmap_zero_page_area(vm_page_t m, int off
 		PMAP_LMEM_UNMAP();
 	}
 }
+#endif
+
+#if defined (__mips_n64)
+void
+pmap_zero_page_idle(vm_page_t m)
+{
+	vm_offset_t va;
+	vm_paddr_t phys = VM_PAGE_TO_PHYS(m);
 
+	va = MIPS_PHYS_TO_XKPHYS_CACHED(phys);
+	bzero((caddr_t)va, PAGE_SIZE);
+	mips_dcache_wbinv_range(va, PAGE_SIZE);
+}
+#else
 void
 pmap_zero_page_idle(vm_page_t m)
 {
@@ -2273,13 +2352,32 @@ pmap_zero_page_idle(vm_page_t m)
 		PMAP_LMEM_UNMAP();
 	}
 }
+#endif
 
 /*
  *	pmap_copy_page copies the specified (machine independent)
  *	page by mapping the page into virtual memory and using
  *	bcopy to copy the page, one machine dependent page at a
  *	time.
+ *
+ * 	Use XKPHYS for 64 bit, and KSEG0 where possible for 32 bit.
  */
+#if defined (__mips_n64)
+void
+pmap_copy_page(vm_page_t src, vm_page_t dst)
+{
+	vm_offset_t va_src, va_dst;
+	vm_paddr_t phy_src = VM_PAGE_TO_PHYS(src);
+	vm_paddr_t phy_dst = VM_PAGE_TO_PHYS(dst);
+
+	pmap_flush_pvcache(src);
+	mips_dcache_wbinv_range_index(MIPS_PHYS_TO_XKPHYS_CACHED(phy_dst), PAGE_SIZE);
+	va_src = MIPS_PHYS_TO_XKPHYS_CACHED(phy_src);
+	va_dst = MIPS_PHYS_TO_XKPHYS_CACHED(phy_dst);
+	bcopy((caddr_t)va_src, (caddr_t)va_dst, PAGE_SIZE);
+	mips_dcache_wbinv_range(va_dst, PAGE_SIZE);
+}
+#else
 void
 pmap_copy_page(vm_page_t src, vm_page_t dst)
 {
@@ -2310,6 +2408,7 @@ pmap_copy_page(vm_page_t src, vm_page_t 
 		PMAP_LMEM_UNMAP();
 	}
 }
+#endif
 
 /*
  * Returns true if the pmap's pv is one of the first
@@ -2715,7 +2814,21 @@ pmap_clear_reference(vm_page_t m)
  * address space. Return a pointer to where it is mapped. This
  * routine is intended to be used for mapping device memory,
  * NOT real memory.
+ *
+ * Use XKPHYS uncached for 64 bit, and KSEG1 where possible for 32 bit.
  */
+#if defined(__mips_n64)
+void *
+pmap_mapdev(vm_offset_t pa, vm_size_t size)
+{
+	return ((void *)MIPS_PHYS_TO_XKPHYS_UNCACHED(pa));
+}
+
+void
+pmap_unmapdev(vm_offset_t va, vm_size_t size)
+{
+}
+#else
 void *
 pmap_mapdev(vm_offset_t pa, vm_size_t size)
 {
@@ -2762,6 +2875,7 @@ pmap_unmapdev(vm_offset_t va, vm_size_t 
 		pmap_kremove(tmpva);
 	kmem_free(kernel_map, base, size);
 }
+#endif
 
 /*
  * perform the pmap work for mincore
@@ -3078,6 +3192,7 @@ pmap_set_modified(vm_offset_t pa)
 	PHYS_TO_VM_PAGE(pa)->md.pv_flags |= (PV_TABLE_REF | PV_TABLE_MOD);
 }
 
+
 /*
  *	Routine:	pmap_kextract
  *	Function:
@@ -3087,41 +3202,68 @@ pmap_set_modified(vm_offset_t pa)
  /* PMAP_INLINE */ vm_offset_t
 pmap_kextract(vm_offset_t va)
 {
-	vm_offset_t pa = 0;
+	int mapped;
+
+	/*
+	 * First, the direct-mapped regions.
+	 */
+#if defined(__mips_n64)
+	if (va >= MIPS_XKPHYS_START && va < MIPS_XKPHYS_END)
+		return (MIPS_XKPHYS_TO_PHYS(va));
+#endif
+
+	if (va >= MIPS_KSEG0_START && va < MIPS_KSEG0_END)
+		return (MIPS_KSEG0_TO_PHYS(va));
 
-	if (va < MIPS_KSEG0_START) {
-		/* user virtual address */
+	if (va >= MIPS_KSEG1_START && va < MIPS_KSEG1_END)
+		return (MIPS_KSEG1_TO_PHYS(va));
+
+	/*
+	 * User virtual addresses.
+	 */
+	if (va < VM_MAXUSER_ADDRESS) {
 		pt_entry_t *ptep;
 
 		if (curproc && curproc->p_vmspace) {
 			ptep = pmap_pte(&curproc->p_vmspace->vm_pmap, va);
-			if (ptep)
-				pa = TLBLO_PTE_TO_PA(*ptep) |
-				    (va & PAGE_MASK);
-		}
-	} else if (va >= MIPS_KSEG0_START &&
-	    va < MIPS_KSEG1_START)
-		pa = MIPS_KSEG0_TO_PHYS(va);
-	else if (va >= MIPS_KSEG1_START &&
-	    va < MIPS_KSEG2_START)
-		pa = MIPS_KSEG1_TO_PHYS(va);
-	else if (va >= MIPS_KSEG2_START && va < VM_MAX_KERNEL_ADDRESS) {
+			if (ptep) {
+				return (TLBLO_PTE_TO_PA(*ptep) |
+				    (va & PAGE_MASK));
+			}
+			return (0);
+		}
+	}
+
+	/*
+	 * Should be kernel virtual here, otherwise fail
+	 */
+	mapped = (va >= MIPS_KSEG2_START || va < MIPS_KSEG2_END);
+#if defined(__mips_n64)
+	mapped = mapped || (va >= MIPS_XKSEG_START || va < MIPS_XKSEG_END);
+#endif 
+	/*
+	 * Kernel virtual.
+	 */
+
+	if (mapped) {
 		pt_entry_t *ptep;
 
 		/* Is the kernel pmap initialized? */
 		if (kernel_pmap->pm_active) {
-			/* Its inside the virtual address range */
+			/* It's inside the virtual address range */
 			ptep = pmap_pte(kernel_pmap, va);
 			if (ptep) {
 				return (TLBLO_PTE_TO_PA(*ptep) |
 				    (va & PAGE_MASK));
 			}
-			return (0);
 		}
+		return (0);
 	}
-	return pa;
+
+	panic("%s for unknown address space %p.", __func__, (void *)va);
 }
 
+
 void 
 pmap_flush_pvcache(vm_page_t m)
 {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201007120938.o6C9cjWD056585>