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