Hi

On 05/07/07 21:48, Peter Tribble wrote:

[cut]
So there is a small chance that back in sfmmu_shadow_hcleanup we could
still see the hblk_cnt and hblk_hmecnt non-zero, which is the comment
you have highlighted.  In that case we do not remove the block from
the hash chain, and proceed on to the next chunk of addresses.
When we unwind back to the sfmmu_tteload_find_hmeblk it could
find this same block again and cause us to descend through the
whole process again.  This won't happen indefinitely since
sooner or later the pageunload will be unpinned and will
decrement the counters allowing us to free the block.

That's how it should work.  If you are spinning in that
stack at and below sfmmu_tteload_find_hmeblk then chances
are that some mismanagement of the hmecnt/vcnt has happened.
This may be verified through some post-mortem crash
analysis.

I have some crash dumps - what should I be looking for?

I'd look at the hash bucket that we appear to be spinning on.  Dig
out the calling arguments to sfmmu_shadow_hcleanup:

384 static void sfmmu_shadow_hcleanup(sfmmu_t *, struct hme_blk *,
385                     struct hmehash_bucket *);

There you have a pointer to the bucket as the last arg - much easier
than trying to find it by computing the hash yourself.


    858 struct hmehash_bucket {
    859         kmutex_t        hmehash_mutex;
    860         uint64_t        hmeh_nextpa;    /* physical address for hash 
list */
    861         struct hme_blk *hmeblkp;
    862         uint_t          hmeh_listlock;
    863 };

Now walk the list of hmeblks off that bucket.  Assuming <addr> is the *hmeblkp 
from
the bucket you dump above:

<addr>::list struct hme_blk hblk_next | ::print -t struct hme_blk

    741 struct hme_blk {
    742         uint64_t        hblk_nextpa;    /* physical address for hash 
list */
    743
    744         hmeblk_tag      hblk_tag;       /* tag used to obtain an hmeblk 
match */
    745
    746         struct hme_blk  *hblk_next;     /* on free list or on hash list 
*/
    747                                         /* protected by hash lock */
    748
    749         struct hme_blk  *hblk_shadow;   /* pts to shadow hblk */
    750                                         /* protected by hash lock */
    751         uint_t          hblk_span;      /* span of memory hmeblk maps */
    752
    753         struct hme_blk_misc     hblk_misc;
    754
    755         union {
    756                 struct {
    757                         ushort_t hblk_hmecount; /* hment on mlists 
counter */
    758                         ushort_t hblk_validcnt; /* valid tte reference 
count */
    759                 } hblk_counts;
    760                 uint_t          hblk_shadow_mask;
    761         } hblk_un;
    762
    763 #ifdef  HBLK_TRACE
    764         kmutex_t        hblk_audit_lock;        /* lock to protect 
index */
    765         uint_t          hblk_audit_index;       /* index into 
audit_cache */
    766         struct  hblk_lockcnt_audit 
hblk_audit_cache[HBLK_AUDIT_CACHE_SIZE];
    767 #endif  /* HBLK_AUDIT */
    768
    769         struct sf_hment hblk_hme[1];    /* hment array */
    770 };

Note that the hblk_hme array has 1 entry as suggested above only for large-page 
mappings.
For 8K mappings it is actually an array of 8 sf_hment, and that is the common 
case of
course.  You can recognise the size of the mappings in this hblk from the 
hblk_misc
member: ttesize there will be 0 (TTE_8K, see pte.h> for 8K mappings.

Actually the sf_hments themselves may not be all that interesting.  The first 
thing
I'd be looking at is the hblk_hmecount and hblk_validcnt in each hblk.  We 
expect
a value from 0 to 8, anything else would be a bug and would likely make as
loop on an unload.

Gavin
_______________________________________________
opensolaris-code mailing list
[email protected]
http://mail.opensolaris.org/mailman/listinfo/opensolaris-code

Reply via email to