Skip to content

Commit 6ec1a67

Browse files
alexandruagandreeaflorescu
authored andcommitted
x86_64/regs: fixed kvm_set_sregs issue
We fixed the setup of special registers in the vCPUs according to the IA-32e specification. Despite using the 32-bit entry point, we start executing guest code in 64-bit mode. According to the specification (see Intel SDM vol. 3, sec. 9.8.5) the following steps are required: (1) Starting from protected mode, disable paging by setting CR0.PG = 0; (2) Enable physical-address extensions (PAE) by setting CR4.PAE = 1; (3) Load CR3 with the physical base address of the Level 4 page map table (PML4); (4) Enable IA-32e mode by setting IA32_EFER.LME = 1; (5) Enable paging by setting CR0.PG = 1. This causes the processor to set the IA32_EFER.LMA bit to 1. Step (1) isn't required since we're not performing a transition but we're setting up the special registers such that we start in 64-bit mode right away. Step (2) and (3) are already performed by setup_page_tables(). Step (4) is already performed by configure_segments_and_sregs(). Step (5) is already partially performed by setup_page_tables(); however, setting IA32_EFER.LMA is missing. Commit f29810335965 ("KVM/x86: Check input paging mode when cs.l is set") in Linux v4.15 improves KVM to honor the specification (the commit has been backported to Linux v4.14.y since it could cause unexpected behavior). This broke our loader, and we fixed it to honor the specification by adding IA32_EFER.LMA = 1. Signed-off-by: Alexandru Agache <[email protected]>
1 parent 4d04f8c commit 6ec1a67

File tree

1 file changed

+2
-1
lines changed

1 file changed

+2
-1
lines changed

x86_64/src/regs.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ const X86_CR0_PE: u64 = 0x1;
167167
const X86_CR0_PG: u64 = 0x80000000;
168168
const X86_CR4_PAE: u64 = 0x20;
169169

170+
const EFER_LMA: u64 = 0x400;
170171
const EFER_LME: u64 = 0x100;
171172

172173
const BOOT_GDT_OFFSET: usize = 0x500;
@@ -225,7 +226,7 @@ fn configure_segments_and_sregs(mem: &GuestMemory, sregs: &mut kvm_sregs) -> Res
225226

226227
/* 64-bit protected mode */
227228
sregs.cr0 |= X86_CR0_PE;
228-
sregs.efer |= EFER_LME;
229+
sregs.efer |= EFER_LME | EFER_LMA;
229230

230231
Ok(())
231232
}

0 commit comments

Comments
 (0)