Closed mcb30 closed 3 years ago
Using the linear
option to inhibit relocation above 4GB will prevent the 0xc000000d
error (at the cost of consuming low memory).
Experimentation so far suggests that the error will occur if any of the bootapp regions describe pages at 4GB or higher.
The error gets reported in winload!MmMapPhysicalAddress
.
As far as I can tell from the disassembly, this is attempting to identity-map any regions mentioned in the BOOTAPP
table. There is a call to a subroutine winload!MmArchTranslateVirtualAddress
which passes in the region start address as a parameter in register %edx
(and hence truncated to 32 bits). When the initrd region is placed above 4GB, this causes winload!MmMapPhysicalAddress
to call winload!MmArchTranslateVirtualAddress
with an incorrect value.
The call to winload!MmArchTranslateVirtualAddress
doesn't actually fail. However, there seems to be a subsequent sanity check in winload!MmMapPhysicalAddress
that will verify that the full 64-bit address was mapped. This check fails and returns the 0xc000000d
error.
My working hypothesis is that this full 64-bit check is present only in more recent Windows versions, very probably as a result of integer-size comparison warnings introduced by newer compilers. This would explain why Windows 7 does not exhibit the same problem.
To test this hypothesis, I hacked src/paging.c
to force the initrd region down close to 0x100000000
(i.e. 4GB). This causes the truncated address to collide with an existing mapping for the region at 1MB. With this forced address, Windows 7 will also fail to boot with error 0xc000000d
.
Raised from #13
The following
.yml
file defines a test case that can reproduce the problem:This test fails for Windows 10 (or Windows 8.1) with a
0xc000000d
error:The test passes if using any 64-bit version of Windows, or if using 32-bit Windows 7.