diff --git a/x86_64/src/regs.rs b/x86_64/src/regs.rs index 7db06fc6ff..2dc48b88ca 100644 --- a/x86_64/src/regs.rs +++ b/x86_64/src/regs.rs @@ -228,9 +228,9 @@ const EFER_LME: u64 = 0x100; const EFER_LMA: u64 = 0x400; const BOOT_GDT_OFFSET: u64 = 0x1500; -const BOOT_IDT_OFFSET: u64 = 0x1520; +const BOOT_IDT_OFFSET: u64 = 0x1528; -const BOOT_GDT_MAX: usize = 4; +const BOOT_GDT_MAX: usize = 5; fn write_gdt_table(table: &[u64], guest_mem: &GuestMemory) -> Result<()> { let boot_gdt_addr = GuestAddress(BOOT_GDT_OFFSET); @@ -258,16 +258,18 @@ fn write_idt_value(val: u64, guest_mem: &GuestMemory) -> Result<()> { /// Configures the GDT, IDT, and segment registers for long mode. pub fn configure_segments_and_sregs(mem: &GuestMemory, sregs: &mut Sregs) -> Result<()> { + // reference: https://docs.kernel.org/arch/x86/boot.html?highlight=__BOOT_CS#id1 let gdt_table: [u64; BOOT_GDT_MAX] = [ + gdt::gdt_entry(0, 0, 0), // NULL gdt::gdt_entry(0, 0, 0), // NULL gdt::gdt_entry(0xa09b, 0, 0xfffff), // CODE gdt::gdt_entry(0xc093, 0, 0xfffff), // DATA gdt::gdt_entry(0x808b, 0, 0xfffff), // TSS ]; - let code_seg = gdt::segment_from_gdt(gdt_table[1], 1); - let data_seg = gdt::segment_from_gdt(gdt_table[2], 2); - let tss_seg = gdt::segment_from_gdt(gdt_table[3], 3); + let code_seg = gdt::segment_from_gdt(gdt_table[2], 2); + let data_seg = gdt::segment_from_gdt(gdt_table[3], 3); + let tss_seg = gdt::segment_from_gdt(gdt_table[4], 4); // Write segments write_gdt_table(&gdt_table[..], mem)?; @@ -344,14 +346,17 @@ mod tests { configure_segments_and_sregs(&gm, &mut sregs).unwrap(); assert_eq!(0x0, read_u64(&gm, BOOT_GDT_OFFSET)); - assert_eq!(0xaf9b000000ffff, read_u64(&gm, BOOT_GDT_OFFSET + 8)); - assert_eq!(0xcf93000000ffff, read_u64(&gm, BOOT_GDT_OFFSET + 16)); - assert_eq!(0x8f8b000000ffff, read_u64(&gm, BOOT_GDT_OFFSET + 24)); + assert_eq!(0xaf9b000000ffff, read_u64(&gm, BOOT_GDT_OFFSET + 0x10)); + assert_eq!(0xcf93000000ffff, read_u64(&gm, BOOT_GDT_OFFSET + 0x18)); + assert_eq!(0x8f8b000000ffff, read_u64(&gm, BOOT_GDT_OFFSET + 0x20)); assert_eq!(0x0, read_u64(&gm, BOOT_IDT_OFFSET)); assert_eq!(0, sregs.cs.base); assert_eq!(0xfffff, sregs.ds.limit); - assert_eq!(0x10, sregs.es.selector); + assert_eq!(0x10, sregs.cs.selector); + assert_eq!(0x18, sregs.ds.selector); + assert_eq!(0x18, sregs.es.selector); + assert_eq!(0x18, sregs.ss.selector); assert_eq!(1, sregs.fs.present); assert_eq!(1, sregs.gs.g); assert_eq!(0, sregs.ss.avl);