Skip to content

Commit 497b4fe

Browse files
christianchristensendianpopa
authored andcommitted
Disable reliance on support of 1GB pages
InstanceStart call causes Firecracker to crash with KVM_EXIT_SHUTDOWN. The problem is the lack of CPU flag: pdpe1gb, i.e. 1GB (huge)pages support by the CPU. solo5 had a similar issue and solved it by switching to 2MB pages for the guest page tables. mato/solo5@68ade81 crosvm have fixed this issue by doing the same thing. https://chromium.googlesource.com/chromiumos/platform/crosvm/+/4567a281a5c28e49479f916a057ee7b1f221925b%5E%21/#F0 Original: @mlctrez patch based on background from @psomas (details in #685) Signed-off-by: Chris Christensen <[email protected]>
1 parent 225dd00 commit 497b4fe

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

x86_64/src/layout.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub const BOOT_STACK_POINTER: usize = 0x8ff0;
1515
// Initial pagetables.
1616
pub const PML4_START: usize = 0x9000;
1717
pub const PDPTE_START: usize = 0xa000;
18+
pub const PDE_START: usize = 0xb000;
1819
// Kernel command line.
1920
pub const CMDLINE_START: usize = 0x20000;
2021
pub const CMDLINE_MAX_SIZE: usize = 0x10000;

x86_64/src/regs.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ pub enum Error {
3636
WriteIDT,
3737
/// Writing PDPTE to RAM failed.
3838
WritePDPTEAddress,
39+
/// Writing PDE to RAM failed.
40+
WritePDEAddress,
3941
/// Writing PML4 to RAM failed.
4042
WritePML4Address,
4143
}
@@ -193,11 +195,24 @@ fn setup_page_tables(mem: &GuestMemory, sregs: &mut kvm_sregs) -> Result<()> {
193195
// Puts PML4 right after zero page but aligned to 4k.
194196
let boot_pml4_addr = GuestAddress(layout::PML4_START);
195197
let boot_pdpte_addr = GuestAddress(layout::PDPTE_START);
198+
let boot_pde_addr = GuestAddress(layout::PDE_START);
196199

200+
// Entry covering VA [0..512GB)
197201
mem.write_obj_at_addr(boot_pdpte_addr.offset() as u64 | 0x03, boot_pml4_addr)
198202
.map_err(|_| Error::WritePML4Address)?;
199-
mem.write_obj_at_addr(0x83u64, boot_pdpte_addr)
203+
204+
// Entry covering VA [0..1GB)
205+
mem.write_obj_at_addr(boot_pde_addr.offset() as u64 | 0x03, boot_pdpte_addr)
200206
.map_err(|_| Error::WritePDPTEAddress)?;
207+
// 512 2MB entries together covering VA [0..1GB). Note we are assuming
208+
// CPU supports 2MB pages (/proc/cpuinfo has 'pse'). All modern CPUs do.
209+
for i in 0..512 {
210+
mem.write_obj_at_addr(
211+
(i << 21) + 0x83u64,
212+
boot_pde_addr.unchecked_add((i * 8) as usize),
213+
).map_err(|_| Error::WritePDEAddress)?;
214+
}
215+
201216
sregs.cr3 = boot_pml4_addr.offset() as u64;
202217
sregs.cr4 |= X86_CR4_PAE;
203218
sregs.cr0 |= X86_CR0_PG;
@@ -310,7 +325,13 @@ mod tests {
310325
setup_page_tables(&gm, &mut sregs).unwrap();
311326

312327
assert_eq!(0xa003, read_u64(&gm, layout::PML4_START));
313-
assert_eq!(0x83, read_u64(&gm, layout::PDPTE_START));
328+
assert_eq!(0xb003, read_u64(&gm, layout::PDPTE_START));
329+
for i in 0..512 {
330+
assert_eq!(
331+
(i << 21) + 0x83u64,
332+
read_u64(&gm, layout::PDE_START + (i * 8) as usize)
333+
);
334+
}
314335

315336
assert_eq!(layout::PML4_START as u64, sregs.cr3);
316337
assert_eq!(X86_CR4_PAE, sregs.cr4);

0 commit comments

Comments
 (0)