This would not detect an unitialized page at the physical address zero, but otherwise should be reliable.
Details
Diff Detail
- Repository
- rG FreeBSD src repository
- Lint
Lint Skipped - Unit
Tests Skipped
Event Timeline
I understand that the immediate objection would be that memset's on the vm_page_array[] are slow and somewhat against the lazy initialization of vm_pages. But this is plain memset instead of the CPU-intensive calculations of proper vm_pages.
This should work against the class of drivers bugs where vma is created against a region that is not registered with the fictitious managed range. I was bitten by drm 6.12 on my new (but quite old) KabyLake notebook.
I don't really understand how this fixes the problem: even if a fictitious range was registered, PHYS_TO_VM_PAGE will try to find the page from the vm_page_array first. What exactly is the driver bug?
Can we make the zeroing conditional on INVARIANTS? Alternately, maybe @cperciva would be willing to benchmark this change in EC2, that was where a lot of the work described here was tested: https://wiki.freebsd.org/BootTime
At the next line we call vm_page_busy_acquire() which dereferences page->object. For uninitialized page, the pointer is a garbage which is interpreted as a non-canonical address. The result is #GP in kernel.
The patch typically converts the panic due to #GP into SIGSEGV delivered to the xorg server on startup, which is in my not so humble opinion is much better than killing the whole machine.
memset() the page array after the call to pmap_page_array_startup(), which handles all arches with pmap array startup.