PERFORCE change 97395 for review

Kip Macy kmacy at FreeBSD.org
Thu May 18 05:54:19 UTC 2006


http://perforce.freebsd.org/chv.cgi?CH=97395

Change 97395 by kmacy at kmacy_storage:sun4v_rwbuf on 2006/05/18 05:53:19

	unlock bucket before panicking
	do more exact tag matching in lookup
	add more info to panic when invalid bit is set

Affected files ...

.. //depot/projects/kmacy_sun4v/src/sys/sun4v/sun4v/tte_hash.c#30 edit

Differences ...

==== //depot/projects/kmacy_sun4v/src/sys/sun4v/sun4v/tte_hash.c#30 (text+ko) ====

@@ -273,17 +273,20 @@
 			if (m == NULL) 
 				VM_WAIT;
 		}
+#if 0
 		if ((m->flags & PG_ZERO) == 0)
+#endif
 			pmap_zero_page(m);
 		fh->thf_head.fh_next = (void *)TLB_PHYS_TO_DIRECT(VM_PAGE_TO_PHYS(m));
 		fh = th->th_fhtail = (void *)TLB_PHYS_TO_DIRECT(VM_PAGE_TO_PHYS(m));
-		printf("allocated new fragment page fh=%p \n", fh);
+		printf("new fh=%p \n", fh);
 
 	} 
 	newfield = fh->thf_entries[++fh->thf_head.fh_free_head].the_fields;
+	bzero(newfield, sizeof(*newfield));
 	fh->thf_head.fh_count++; 
 
-	return (&newfield[0]);
+	return (newfield);
 }
 
 /*
@@ -297,26 +300,32 @@
 
 
 static __inline tte_t 
-tte_hash_lookup_inline(tte_hash_field_t fields, vm_offset_t va, boolean_t setfield)
+tte_hash_lookup_inline(tte_hash_field_t sfields, tte_t tte_tag, boolean_t setfield)
 {
 	int i;
 	tte_t entry;
+	tte_hash_field_t fields;
 
-	/* XXX - only handle 8K pages for now */
 
+	fields = sfields;
 	entry = 0;
-
 retry:
 	for (i = 0; i < HASH_ENTRIES && fields[i].tte.tag != 0; i++) {
-		if (((fields[i].tte.tag << TTARGET_VA_SHIFT) == (va & ~PAGE_MASK_4M))) {
+		if (tte_tag == fields[i].tte.tag) {
 			entry = (fields[i].tte.data & ~VTD_LOCK);
 			break;
 		}
 	}
 	if (i == HASH_ENTRIES) {
 #ifdef DEBUG
-		if (fields[(HASH_ENTRIES - 1)].of.flags & TH_INVALID)
-			panic("invalid bit set");
+		if (fields[(HASH_ENTRIES - 1)].of.flags & TH_INVALID) {
+			hash_bucket_unlock(sfields, PSTATE_KERNEL);
+			printf("invalid bit set in lookup flags=0x%lx next=%p (sf=f):%d\n", 
+			       fields[(HASH_ENTRIES - 1)].of.flags, 
+			       fields[(HASH_ENTRIES - 1)].of.next, 
+			       (sfields==fields));
+			panic("bad flags");
+		}
 #endif
 		if (fields[(HASH_ENTRIES - 1)].of.flags == TH_COLLISION) {
 			fields = fields[(HASH_ENTRIES - 1)].of.next;
@@ -325,9 +334,6 @@
 		i = (HASH_ENTRIES - 1);
 	} 
 
-	if (i >= HASH_ENTRIES)
-		panic("invalid state");
-
 	if (setfield == TRUE) 
 		PCPU_SET(lookup_field, (u_long)&fields[i]);
 
@@ -336,30 +342,36 @@
 
 
 static __inline void
-tte_hash_lookup_last_inline(tte_hash_field_t fields, vm_offset_t va)
+tte_hash_lookup_last_inline(tte_hash_field_t sfields)
 {
-	int i, index;
-	/* XXX - only handle 8K pages for now */
-	index = -1;;
-	
 
+	int i, depth;
+	tte_hash_field_t fields;
+       
+	depth = 0;
+	fields = sfields;
 retry:
 	for (i = 0; i < (HASH_ENTRIES - 1); i++) 
-		if (fields[i + 1].tte.tag == 0) {
-			index = i;
+		if (fields[i + 1].tte.tag == 0) 
 			break;
-		}
 
-	if (index != -1) 
-		PCPU_SET(last_field, (u_long)&fields[index]);
+	if (i < (HASH_ENTRIES - 1))
+		PCPU_SET(last_field, (u_long)&fields[i]);
 	else {
 #ifdef DEBUG
-		if (fields[(HASH_ENTRIES - 1)].of.flags & TH_INVALID)
-			panic("invalid bit set");
+		if (fields[(HASH_ENTRIES - 1)].of.flags & TH_INVALID) {
+			hash_bucket_unlock(sfields, PSTATE_KERNEL);
+			printf("invalid bit set in lookup_last flags=0x%lx next=%p (sf=f):%d, depth=%d", 
+			       fields[(HASH_ENTRIES - 1)].of.flags, 
+			       fields[(HASH_ENTRIES - 1)].of.next, 
+			       (sfields==fields), depth);
+			panic("bad flags");
+		}
 #endif
 		if (fields[(HASH_ENTRIES - 1)].of.flags == TH_COLLISION) {
 			if (fields[(HASH_ENTRIES - 1)].of.next[0].tte.tag != 0) {
 				fields = fields[(HASH_ENTRIES - 1)].of.next; 
+				depth++;
 				goto retry;
 			} else {
 				/* 3rd entry is last */
@@ -379,15 +391,17 @@
 {
 	uint64_t hash_shift, hash_index, s;
 	tte_hash_field_t fields;
-	tte_t otte_data;
+	tte_t otte_data, tte_tag;
 
 	/* XXX - only handle 8K pages for now */
 	hash_shift = PAGE_SHIFT;
 	hash_index = (va >> hash_shift) & HASH_MASK(th);
 	fields = (th->th_hashtable[hash_index].the_fields);
 
+	tte_tag = (((uint64_t)th->th_context << TTARGET_CTX_SHIFT)|(va >> TTARGET_VA_SHIFT));
+	
 	s = hash_bucket_lock(fields);
-	if((otte_data = tte_hash_lookup_inline(fields, va, TRUE)) != 0)
+	if((otte_data = tte_hash_lookup_inline(fields, tte_tag, TRUE)) != 0)
 		tte_hash_set_field((tte_hash_field_t)PCPU_GET(lookup_field), 
 				   ((tte_hash_field_t)PCPU_GET(lookup_field))->tte.tag, 
 				   ((tte_hash_field_t)PCPU_GET(lookup_field))->tte.data & ~flags);
@@ -402,20 +416,21 @@
 {
 	uint64_t hash_shift, hash_index, s;
 	tte_hash_field_t fields;
-	tte_t tte_data;
+	tte_t tte_data, tte_tag;
 	/* XXX - only handle 8K pages for now */
 
 	hash_shift = PAGE_SHIFT;
 	hash_index = (va >> hash_shift) & HASH_MASK(th);
 	fields = (th->th_hashtable[hash_index].the_fields);
 
+	tte_tag = (((uint64_t)th->th_context << TTARGET_CTX_SHIFT)|(va >> TTARGET_VA_SHIFT));
 
 	s  = hash_bucket_lock(fields);
 	
-	if ((tte_data = tte_hash_lookup_inline(fields, va, TRUE)) == 0) 
+	if ((tte_data = tte_hash_lookup_inline(fields, tte_tag, TRUE)) == 0) 
 		goto done;
 
-	tte_hash_lookup_last_inline(fields, va);
+	tte_hash_lookup_last_inline(fields);
 
 #ifdef DEBUG
 	if (((tte_hash_field_t)PCPU_GET(last_field))->tte.tag == 0) {
@@ -435,7 +450,10 @@
 
 	if (tte_data)
 		th->th_entries--;
-
+#ifdef DEBUG
+	if (tte_hash_lookup(th, va) != 0) 
+		panic("tte_hash_delete failed");
+#endif
 	return (tte_data);
 }
 
@@ -443,9 +461,9 @@
 tte_hash_insert(tte_hash_t th, vm_offset_t va, tte_t tte_data)
 {
 
-	uint64_t hash_shift, hash_index, tte_tag, s;
+	uint64_t hash_shift, hash_index, s;
 	tte_hash_field_t fields, newfield;
-	tte_t otte_data;
+	tte_t otte_data, tte_tag;
 
 	/* XXX - only handle 8K pages for now */
 	hash_shift = PAGE_SHIFT;
@@ -455,7 +473,13 @@
 	tte_tag = (((uint64_t)th->th_context << TTARGET_CTX_SHIFT)|(va >> TTARGET_VA_SHIFT));
 
 	s = hash_bucket_lock(fields);
-	otte_data = tte_hash_lookup_inline(fields, va, TRUE);
+	otte_data = tte_hash_lookup_inline(fields, tte_tag, TRUE);
+#ifdef DEBUG
+	if (otte_data) {
+		hash_bucket_unlock(fields, s);
+		panic("mapping for va=0x%lx already exists tte_data=0x%lx\n", va, otte_data);
+	}
+#endif
 	if (((tte_hash_field_t)PCPU_GET(lookup_field))->tte.tag != 0) {
 		hash_bucket_unlock(fields, s);
 		newfield = tte_hash_allocate_fragment_entry(th); 
@@ -466,16 +490,17 @@
 
 		((tte_hash_field_t)PCPU_GET(lookup_field))->of.flags = TH_COLLISION;
 		((tte_hash_field_t)PCPU_GET(lookup_field))->of.next = newfield;
-		otte_data = tte_hash_lookup_inline(fields, va, TRUE);
+		PCPU_SET(lookup_field, (u_long)&newfield[1]);
 	}
 	
+	tte_hash_set_field((tte_hash_field_t)PCPU_GET(lookup_field), tte_tag, tte_data);
+
+	hash_bucket_unlock(fields, s);
 #ifdef DEBUG
-	if (otte_data)
-		panic("mapping for va=0x%lx already exists tte_data=0x%lx\n", va, otte_data);
+	if (tte_hash_lookup(th, va) == 0) 
+		panic("tte_hash_insert failed");
 #endif
-	tte_hash_set_field((tte_hash_field_t)PCPU_GET(lookup_field), tte_tag, tte_data);
 
-	hash_bucket_unlock(fields, s);
 	th->th_entries++;
 }
 
@@ -492,15 +517,17 @@
 {
 	uint64_t hash_shift, hash_index, s;
 	tte_hash_field_t fields;
-	tte_t tte_data;
+	tte_t tte_data, tte_tag;
 	/* XXX - only handle 8K pages for now */
 
 	hash_shift = PAGE_SHIFT;
 	hash_index = (va >> hash_shift) & HASH_MASK(th);
 	fields = (th->th_hashtable[hash_index].the_fields);
 
+	tte_tag = (((uint64_t)th->th_context << TTARGET_CTX_SHIFT)|(va >> TTARGET_VA_SHIFT));
+
 	s = hash_bucket_lock(fields);
-	tte_data = tte_hash_lookup_inline(fields, va, FALSE);
+	tte_data = tte_hash_lookup_inline(fields, tte_tag, FALSE);
 	hash_bucket_unlock(fields, s);
 	
 	return (tte_data);
@@ -542,18 +569,18 @@
 {
 	uint64_t hash_shift, hash_index;
 	tte_hash_field_t fields, newfield;
-	tte_t otte_data;
-	uint64_t tag, s;
+	tte_t otte_data, tte_tag;
+	uint64_t s;
 
 	/* XXX - only handle 8K pages for now */
 	hash_shift = PAGE_SHIFT;
 	hash_index = (va >> hash_shift) & HASH_MASK(th);
 	fields = (th->th_hashtable[hash_index].the_fields);
 
-	tag = (((uint64_t)th->th_context << TTARGET_CTX_SHIFT)|(va >> TTARGET_VA_SHIFT));
+	tte_tag = (((uint64_t)th->th_context << TTARGET_CTX_SHIFT)|(va >> TTARGET_VA_SHIFT));
 
 	s = hash_bucket_lock(fields);
-	otte_data = tte_hash_lookup_inline(fields, va, TRUE);
+	otte_data = tte_hash_lookup_inline(fields, tte_tag, TRUE);
 
 	if (otte_data == 0 && ((tte_hash_field_t)PCPU_GET(lookup_field))->tte.tag != 0) {
 		hash_bucket_unlock(fields, s);
@@ -565,15 +592,19 @@
 
 		((tte_hash_field_t)PCPU_GET(lookup_field))->of.flags = TH_COLLISION;
 		((tte_hash_field_t)PCPU_GET(lookup_field))->of.next = newfield;
-		otte_data = tte_hash_lookup_inline(fields, va, TRUE);
+		PCPU_SET(lookup_field, (u_long)&newfield[1]);
 	}
 	
-	tte_hash_set_field((tte_hash_field_t)PCPU_GET(lookup_field), tag, tte_data);
+	tte_hash_set_field((tte_hash_field_t)PCPU_GET(lookup_field), tte_tag, tte_data);
 
 	hash_bucket_unlock(fields, s);
 
 	if (otte_data == 0)
 		th->th_entries++;
 
+#ifdef DEBUG
+	if (tte_hash_lookup(th, va) == 0) 
+		panic("tte_hash_update failed");
+#endif
 	return (otte_data);
 }


More information about the p4-projects mailing list