Date: Thu, 18 May 2006 05:53:54 GMT From: Kip Macy <kmacy@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 97395 for review Message-ID: <200605180553.k4I5rs8o020701@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=97395 Change 97395 by kmacy@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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200605180553.k4I5rs8o020701>