static ZVMSTATUS HvmSetupGdt ( PCPU Cpu ) { uint64_t GuestTssBase; uint8_t GuestTssLimit; PSEGMENT_DESCRIPTOR GuestTssDescriptor; if (!Cpu || !Cpu->GdtArea) return ZVM_INVALID_PARAMETER; memcpy (Cpu->GdtArea, (void *) GetGdtBase(), GetGdtLimit()); CmReloadGdtr(Cpu->GdtArea, GetGdtLimit());//加载Cpu->GdtArea中的GDT表 return ZVMSUCCESS; }
/** * effects: Clone GDT into CPU Struct */ static NTSTATUS _HvmSetupGdt ( PCPU Cpu ) { //Finish ULONG64 GuestTssBase; USHORT GuestTssLimit; PSEGMENT_DESCRIPTOR GuestTssDescriptor; if (!Cpu || !Cpu->GdtArea) return STATUS_INVALID_PARAMETER; memcpy (Cpu->GdtArea, (PVOID) GetGdtBase(), GetGdtLimit()); CmReloadGdtr(Cpu->GdtArea, GetGdtLimit()); return STATUS_SUCCESS; //#if DEBUG_LEVEL>2 // CmDumpGdt ((PUCHAR)GetGdtBase(), 0x67); //(USHORT)GetGdtLimit()); //#endif // // // set code and stack selectors the same with NT to simplify our unloading // CmSetGdtEntry (Cpu->GdtArea, // BP_GDT_LIMIT, // BP_GDT64_CODE, // 0, 0, LA_STANDARD | LA_DPL_0 | LA_CODE | LA_PRESENT | LA_READABLE | LA_ACCESSED, HA_LONG); // // // we don't want to have a separate segment for DS and ES. They will be equal to SS. // CmSetGdtEntry (Cpu->GdtArea, // BP_GDT_LIMIT, // BP_GDT64_DATA, // 0, 0xfffff, LA_STANDARD | LA_DPL_0 | LA_PRESENT | LA_WRITABLE | LA_ACCESSED, HA_GRANULARITY | HA_DB); // // // fs // CmSetGdtEntry (Cpu->GdtArea, // BP_GDT_LIMIT, // KGDT64_R3_CMTEB, 0, 0x3c00, LA_STANDARD | LA_DPL_3 | LA_PRESENT | LA_WRITABLE | LA_ACCESSED, HA_DB); // // // gs // CmSetGdtEntry (Cpu->GdtArea, // BP_GDT_LIMIT, // KGDT64_R3_DATA, // 0, 0xfffff, LA_STANDARD | LA_DPL_3 | LA_PRESENT | LA_WRITABLE | LA_ACCESSED, HA_GRANULARITY | HA_DB); // // GuestTssDescriptor = (PSEGMENT_DESCRIPTOR) (GetGdtBase () + GetTrSelector ()); // // GuestTssBase = GuestTssDescriptor->base0 | GuestTssDescriptor->base1 << 16 | GuestTssDescriptor->base2 << 24; // GuestTssLimit = GuestTssDescriptor->limit0 | (GuestTssDescriptor->limit1attr1 & 0xf) << 16; // if (GuestTssDescriptor->limit1attr1 & 0x80) // // 4096-bit granularity is enabled for this segment, scale the limit // GuestTssLimit <<= 12; // // if (!(GuestTssDescriptor->attr0 & 0x10)) // { // GuestTssBase = (*(PULONG64) ((PUCHAR) GuestTssDescriptor + 4)) & 0xffffffffff000000; // GuestTssBase |= (*(PULONG32) ((PUCHAR) GuestTssDescriptor + 2)) & 0x00ffffff; // } //#if DEBUG_LEVEL>2 // CmDumpTSS64 ((PTSS64) GuestTssBase, GuestTssLimit); //#endif // // MmMapGuestTSS64 ((PTSS64) GuestTssBase, GuestTssLimit); // // // don't need to reload TR - we use 0x40, as in xp/vista. // CmSetGdtEntry (Cpu->GdtArea, BP_GDT_LIMIT, BP_GDT64_SYS_TSS, (PVOID) GuestTssBase, GuestTssLimit, //BP_TSS_LIMIT, // LA_BTSS64 | LA_DPL_0 | LA_PRESENT | LA_ACCESSED, 0); // // // so far, we have 5 GDT entries. // // 0x10: CODE64 cpl0 CS // // 0x18: DATA dpl0 DS, ES, SS // // 0x28: DATA dpl3 GS // // 0x40: Busy TSS64, base is equal to NT TSS TR // // 0x50: DATA dpl3 FS // //#if DEBUG_LEVEL>2 // CmDumpGdt ((PUCHAR) Cpu->GdtArea, BP_GDT_LIMIT); //#endif // // CmReloadGdtr (Cpu->GdtArea, BP_GDT_LIMIT); // // // set new DS and ES // CmSetBluepillESDS (); // // // we will use GS as our PCR pointer; GS base will be set to the Cpu in HvmEventCallback // // FIXME: but it is not? // // return STATUS_SUCCESS; }