Module Name:    src
Committed By:   matt
Date:           Wed Jul 18 18:29:22 UTC 2012

Modified Files:
        src/sys/arch/powerpc/booke: e500_tlb.c

Log Message:
Fix some SHIFTOUT to SHIFTIN
Add a lookup of tlb1 by pa.  fix comparisions of xtlb entries by using
masks.  (since xtlb can looked up by pa & va and va may not equal pa).


To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/powerpc/booke/e500_tlb.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/powerpc/booke/e500_tlb.c
diff -u src/sys/arch/powerpc/booke/e500_tlb.c:1.8 src/sys/arch/powerpc/booke/e500_tlb.c:1.9
--- src/sys/arch/powerpc/booke/e500_tlb.c:1.8	Thu Mar 29 15:48:20 2012
+++ src/sys/arch/powerpc/booke/e500_tlb.c	Wed Jul 18 18:29:22 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: e500_tlb.c,v 1.8 2012/03/29 15:48:20 matt Exp $	*/
+/*	$NetBSD: e500_tlb.c,v 1.9 2012/07/18 18:29:22 matt Exp $	*/
 /*-
  * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -38,7 +38,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(0, "$NetBSD: e500_tlb.c,v 1.8 2012/03/29 15:48:20 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: e500_tlb.c,v 1.9 2012/07/18 18:29:22 matt Exp $");
 
 #include <sys/param.h>
 
@@ -318,7 +318,7 @@ e500_alloc_tlb1_entry(void)
 	const u_int slot = tlb1->tlb1_freelist[--tlb1->tlb1_numfree];
 	KASSERT((tlb1->tlb1_entries[slot].e_hwtlb.hwtlb_mas1 & MAS1_V) == 0);
 	tlb1->tlb1_entries[slot].e_hwtlb.hwtlb_mas0 = 
-	    MAS0_TLBSEL_TLB1 | __SHIFTOUT(slot, MAS0_ESEL);
+	    MAS0_TLBSEL_TLB1 | __SHIFTIN(slot, MAS0_ESEL);
 	return (int)slot;
 }
 
@@ -644,7 +644,7 @@ e500_tlb_walk(void *ctx, bool (*func)(vo
 }
 
 static struct e500_xtlb *
-e500_tlb_lookup_xtlb(vaddr_t va, u_int *slotp)
+e500_tlb_lookup_xtlb_pa(vaddr_t pa, u_int *slotp)
 {
 	struct e500_tlb1 * const tlb1 = &e500_tlb1;
 	struct e500_xtlb *xtlb = tlb1->tlb1_entries;
@@ -653,9 +653,31 @@ e500_tlb_lookup_xtlb(vaddr_t va, u_int *
 	 * See if we have a TLB entry for the pa.
 	 */
 	for (u_int i = 0; i < tlb1->tlb1_numentries; i++, xtlb++) {
+		psize_t mask = ~(xtlb->e_tlb.tlb_size - 1);
+		if ((xtlb->e_hwtlb.hwtlb_mas1 & MAS1_V)
+		    && ((pa ^ xtlb->e_tlb.tlb_pte) & mask) == 0) {
+			if (slotp != NULL)
+				*slotp = i;
+			return xtlb;
+		}
+	}
+
+	return NULL;
+}
+
+static struct e500_xtlb *
+e500_tlb_lookup_xtlb(vaddr_t va, u_int *slotp)
+{
+	struct e500_tlb1 * const tlb1 = &e500_tlb1;
+	struct e500_xtlb *xtlb = tlb1->tlb1_entries;
+
+	/*
+	 * See if we have a TLB entry for the va.
+	 */
+	for (u_int i = 0; i < tlb1->tlb1_numentries; i++, xtlb++) {
+		vsize_t mask = ~(xtlb->e_tlb.tlb_size - 1);
 		if ((xtlb->e_hwtlb.hwtlb_mas1 & MAS1_V)
-		    && xtlb->e_tlb.tlb_va <= va
-		    && va < xtlb->e_tlb.tlb_va + xtlb->e_tlb.tlb_size) {
+		    && ((va ^ xtlb->e_tlb.tlb_va) & mask) == 0) {
 			if (slotp != NULL)
 				*slotp = i;
 			return xtlb;
@@ -675,9 +697,10 @@ e500_tlb_lookup_xtlb2(vaddr_t va, vsize_
 	 * See if we have a TLB entry for the pa.
 	 */
 	for (u_int i = 0; i < tlb1->tlb1_numentries; i++, xtlb++) {
+		vsize_t mask = ~(xtlb->e_tlb.tlb_size - 1);
 		if ((xtlb->e_hwtlb.hwtlb_mas1 & MAS1_V)
-		    && xtlb->e_tlb.tlb_va < va + len
-		    && va < xtlb->e_tlb.tlb_va + xtlb->e_tlb.tlb_size) {
+		    && ((va ^ xtlb->e_tlb.tlb_va) & mask) == 0
+		    && (((va + len - 1) ^ va) & mask) == 0) {
 			return xtlb;
 		}
 	}
@@ -688,7 +711,7 @@ e500_tlb_lookup_xtlb2(vaddr_t va, vsize_
 static void *
 e500_tlb_mapiodev(paddr_t pa, psize_t len, bool prefetchable)
 {
-	struct e500_xtlb * const xtlb = e500_tlb_lookup_xtlb(pa, NULL);
+	struct e500_xtlb * const xtlb = e500_tlb_lookup_xtlb_pa(pa, NULL);
 
 	/*
 	 * See if we have a TLB entry for the pa.  If completely falls within
@@ -696,7 +719,6 @@ e500_tlb_mapiodev(paddr_t pa, psize_t le
 	 * is not cacheable.
 	 */
 	if (xtlb
-	    && pa + len <= xtlb->e_tlb.tlb_va + xtlb->e_tlb.tlb_size
 	    && (prefetchable
 		|| (xtlb->e_tlb.tlb_pte & PTE_WIG) == (PTE_I|PTE_G))) {
 		xtlb->e_refcnt++;
@@ -726,13 +748,12 @@ e500_tlb_ioreserve(vaddr_t va, vsize_t l
 	KASSERT(len >= PAGE_SIZE);
 	KASSERT((len & (len - 1)) == 0);
 	KASSERT((va & (len - 1)) == 0);
-	KASSERT((pte & (len - 1)) == 0);
+	KASSERT(((pte & PTE_RPN_MASK) & (len - 1)) == 0);
 
 	if ((xtlb = e500_tlb_lookup_xtlb2(va, len)) != NULL) {
-		if (va < xtlb->e_tlb.tlb_va
-		    || xtlb->e_tlb.tlb_va + xtlb->e_tlb.tlb_size < va + len
-		    || va - xtlb->e_tlb.tlb_va != pte - xtlb->e_tlb.tlb_pte)
-			return EBUSY;
+		psize_t mask = ~(xtlb->e_tlb.tlb_size - 1);
+		KASSERT(len <= xtlb->e_tlb.tlb_size);
+		KASSERT((pte & mask) == (xtlb->e_tlb.tlb_pte & mask));
 		xtlb->e_refcnt++;
 		return 0;
 	}
@@ -748,7 +769,7 @@ e500_tlb_ioreserve(vaddr_t va, vsize_t l
 	xtlb->e_tlb.tlb_asid = KERNEL_PID;
 
 	xtlb->e_hwtlb = tlb_to_hwtlb(xtlb->e_tlb);
-	xtlb->e_hwtlb.hwtlb_mas0 |= __SHIFTOUT(slot, MAS0_ESEL);
+	xtlb->e_hwtlb.hwtlb_mas0 |= __SHIFTIN(slot, MAS0_ESEL);
 	hwtlb_write(xtlb->e_hwtlb, true);
 	return 0;
 }
@@ -950,7 +971,7 @@ e500_tlb_init(vaddr_t endkernel, psize_t
 		kxtlb->e_tlb.tlb_asid = KERNEL_PID;
 
 		kxtlb->e_hwtlb = tlb_to_hwtlb(kxtlb->e_tlb);
-		kxtlb->e_hwtlb.hwtlb_mas0 |= __SHIFTOUT(kslot, MAS0_ESEL);
+		kxtlb->e_hwtlb.hwtlb_mas0 |= __SHIFTIN(kslot, MAS0_ESEL);
 		kxtlb->e_hwtlb.hwtlb_mas1 |= MAS1_TS;
 		hwtlb_write(kxtlb->e_hwtlb, true);
 

Reply via email to