NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/51254 (uvm assertion "!topdown || hint <= orig_hint" failed)



> Date: Fri, 25 Nov 2022 23:24:00 +0900
> From: Rin Okuyama <rokuyama.rk%gmail.com@localhost>
> 
> >>       end_markers: [ 2036.0781860] panic: kernel diagnostic assertion "!topdown || hint <= orig_hint" failed: file "../../../../uvm/uvm_map.c", line 1795 map=0x8fe48d68 hint=0x7defb000 orig_hint=0x75172000 length=0x1000 uobj=0x8fd5eaa0 uoffset=0 align=0 flags=0x101 entry=0x8dfc6864 (uvm_map_findspace line 2011)
> [...]
>   - 0x8dfc6864: 0x75170000->0x75172000: obj=0x0/0, amap=0x8e01e32c/0
>          submap=F, cow=T, nc=F, prot(max)=3/3, inh=1, wc=0, adv=0
>   - 0x8fb5b7a8: 0x7defc000->0x7defd000: obj=0x8fe517c0/0, amap=0x0/0
>          submap=F, cow=F, nc=F, prot(max)=5/5, inh=0, wc=0, adv=1

What's happening is that, at uvm_map.c rev. 1.403 line 2006, we have
entry=0x8dfc6864 covering [0x75170000, 0x75172000), followed by
0x8fb5b7a8 covering [0x7defc000, 0x7defd000).  But orig_hint is
0x75172000.  So we have (addresses growing down):

0x75170000 entry@0x8dfc6864->start
...
0x75172000 entry@0x8dfc6864->end; orig_hint
...
0x7defb000 entry->next->start - length; new hint
...
0x7defc000 entry->next->start
...
0x7defd000 entry->next->end

How we got here must be:

1. condition on lines 1911 false (orig hint is not vm map min/max)
2. condition on line 1942 false (orig hint is not in a mapped entry),
   but this sets entry=0x8dfc6864 to be the highest-address entry
   before the orig hint (0x75172000)
3. condition on line 1951 false (not asking for fixed mapping)
   => if we had taken this branch, then the conditions on lines
      1954-1955 would have covered this and gone to found, so we must
      not have taken this branch
4. uvm_map_space_avail on lines 1964-1965 must have failed to find
   space in this gap, even though there appears to be space here for a
   single page

Then we get to the (newly modified) logic on lines 1997-2010, which
sets hint = entry->next->start - length = 0x7defb000 which lives above
orig_hint and trips over the assertion.

Now here I'm a bit puzzled.  We started with orig_hint=0x75172000.
Why didn't uvm_map_space_avail find any space in the gap [0x75172000,
0x7defc000) between entry and entry->next?  Is this something about
PMAP_PREFER on sh3, or what?

If it is legitimate for uvm_map_space_avail to have failed in that
scenario, then we need some mechanism to ensure that we don't move to
higher addresses in the gap after it fails (because that certainly
won't help in the search, since it makes the gap smaller than the one
that already failed, and will violate the monotonicity that this
search is supposed to follow).

Can you try the attached patch?
From 9b46875ee5560b45989709b0e1f378b2c6e9c6a3 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Fri, 25 Nov 2022 14:50:42 +0000
Subject: [PATCH] uvm: Ensure topdown search through gap only tries lower
 addresses.

Otherwise (a) we might waste time checking for space in smaller gap
after a larger one already failed, and (b) we violate the monotonic
search.

PR kern/51254
---
 sys/uvm/uvm_map.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/uvm/uvm_map.c b/sys/uvm/uvm_map.c
index 2d6ff6c83eb7..4fb68ac80541 100644
--- a/sys/uvm/uvm_map.c
+++ b/sys/uvm/uvm_map.c
@@ -2003,7 +2003,7 @@ uvm_map_findspace(struct vm_map *map, vaddr_t hint, vsize_t length,
 		if (length > entry->next->start - vm_map_min(map))
 			hint = vm_map_min(map); /* XXX goto wraparound? */
 		else
-			hint = entry->next->start - length;
+			hint = MIN(orig_hint, entry->next->start - length);
 		KASSERT(hint >= vm_map_min(map));
 	} else {
 		hint = entry->end;


Home | Main Index | Thread Index | Old Index