PS3 livelock and pmap_remove()
Nathan Whitehorn
nwhitehorn at freebsd.org
Tue Sep 7 14:29:45 UTC 2010
On 09/06/10 22:24, Nathan Whitehorn wrote:
> On 09/06/10 20:22, Nathan Whitehorn wrote:
>
>> Now that my SLB allocation issue is solved, with help with Matthew and
>> Alan, I have another VM puzzler.
>>
>> I have a simple program that tries to use all the memory on the system,
>> which isn't very much on the PS3, so I use it to test swap as well.
>> Shortly after it begins paging, the system locks up completely. I
>> managed to duplicate this behavior on an emulator, and found out what it
>> is actually doing. Somehow pmap_remove() is being called with arguments
>> pmap_remove(userpmap, PAGE_SIZE, VM_MAXUSER_ADDRESS = USRSTACK). For
>> powerpc64, VM_MAXUSER_ADDRESS is 0x7ffffffffffff000, so there are 10^15
>> pages to unmap in that range and it was busy taking until the end of
>> time unmapping them all.
>>
>> Here's the trace from KDB:
>>
>> moea64_remove()
>> pmap_remove()
>> vm_daemon()
>> fork_exit()
>> fork_trampoline()
>> ----end-----
>>
>> Does anyone have any idea why this is happening?
>>
>>
>>
> The culprit here is lines 703-706 of vm/vm_pageout.c:
>
> if (desired == 0 && nothingwired) {
> pmap_remove(vm_map_pmap(map), vm_map_min(map),
> vm_map_max(map));
> }
>
> It would be much better if it did this in sections, the way
> vm_map_delete does. I'll take a crack at this, though any suggestions
> for proper implementation would be appreciated.
> -nathan
>
I've attached a patch that reimplements this by unmapping each map_entry
separately, which solves the problem on PowerPC and I believe is
functionally equivalent. My PS3 successfully completes a buildworld with
this patch. Are there any objections to me committing it?
-Nathan
-------------- next part --------------
Index: vm/vm_pageout.c
===================================================================
--- vm/vm_pageout.c (revision 212277)
+++ vm/vm_pageout.c (working copy)
@@ -701,8 +701,11 @@
* table pages.
*/
if (desired == 0 && nothingwired) {
- pmap_remove(vm_map_pmap(map), vm_map_min(map),
- vm_map_max(map));
+ tmpe = map->header.next;
+ while (tmpe != &map->header) {
+ pmap_remove(vm_map_pmap(map), tmpe->start, tmpe->end);
+ tmpe = tmpe->next;
+ }
}
vm_map_unlock(map);
}
More information about the freebsd-hackers
mailing list