- Add a 16-bit code and data segment to cstart.S. - Move ring 3 segment descriptors at the end of the GDT, and lay them out as required by syscall/sysret in cstart64.S. - Only define TSS_INTR for 32-bit, and place it where cstart64.S puts the 32-bit ring 0 segment. - Document that the same data segment can be used for 32 and 64-bit code. - Mark all descriptors as accessed. Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx> --- lib/x86/desc.c | 13 ------------- lib/x86/desc.h | 59 ++++++++++++++++++++++++++++++++++++++++++++++------------ x86/cstart.S | 16 ++++++++-------- x86/cstart64.S | 12 ++++++------ 4 files changed, 61 insertions(+), 39 deletions(-) diff --git a/lib/x86/desc.c b/lib/x86/desc.c index 4747b32..6144a3d 100644 --- a/lib/x86/desc.c +++ b/lib/x86/desc.c @@ -262,19 +262,6 @@ bool exception_rflags_rf(void) static char intr_alt_stack[4096]; #ifndef __x86_64__ -/* - * GDT, with 6 entries: - * 0x00 - NULL descriptor - * 0x08 - Code segment (ring 0) - * 0x10 - Data segment (ring 0) - * 0x18 - Not present code segment (ring 0) - * 0x20 - Code segment (ring 3) - * 0x28 - Data segment (ring 3) - * 0x30 - Interrupt task - * 0x38 to 0x78 - Free to use for test cases - * 0x80 - Primary task (CPU 0) - */ - void set_gdt_entry(int sel, u32 base, u32 limit, u8 access, u8 gran) { int num = sel >> 3; diff --git a/lib/x86/desc.h b/lib/x86/desc.h index be52fd4..e7edb4f 100644 --- a/lib/x86/desc.h +++ b/lib/x86/desc.h @@ -85,24 +85,59 @@ typedef struct __attribute__((packed)) { #define UD_VECTOR 6 #define GP_VECTOR 13 -#define KERNEL_CS 0x08 -#define KERNEL_DS 0x10 -#define NP_SEL 0x18 -#define USER_CS 0x23 -#define USER_DS 0x2b +/* + * selector 32-bit 64-bit + * 0x00 NULL descriptor NULL descriptor + * 0x08 ring-0 code segment (32-bit) ring-0 code segment (64-bit) + * 0x10 ring-0 data segment (32-bit) ring-0 data segment (32/64-bit) + * 0x18 ring-0 code segment (P=0) ring-0 code segment (64-bit, P=0) + * 0x20 intr_alt_stack TSS ring-0 code segment (32-bit) + * 0x28 ring-0 code segment (16-bit) same + * 0x30 ring-0 data segment (16-bit) same + * 0x38 (0x3b) ring-3 code segment (32-bit) same + * 0x40 (0x43) ring-3 data segment (32-bit) ring-3 data segment (32/64-bit) + * 0x48 (0x4b) **unused** ring-3 code segment (64-bit) + * 0x50--0x78 free to use for test cases same + * 0x80 primary TSS (CPU 0) same + * + * Note that the same segment can be used for 32-bit and 64-bit data segments + * (the L bit is only defined for code segments) + * + * Selectors 0x08-0x10 and 0x3b-0x4b are set up for use with the SYSCALL + * and SYSRET instructions. + */ + +#define KERNEL_CS 0x08 +#define KERNEL_DS 0x10 +#define NP_SEL 0x18 +#ifdef __x86_64__ +#define KERNEL_CS32 0x20 +#else +#define TSS_INTR 0x20 +#endif +#define KERNEL_CS16 0x28 +#define KERNEL_DS16 0x30 +#define USER_CS32 0x3b +#define USER_DS 0x43 +#ifdef __x86_64__ +#define USER_CS64 0x4b +#endif + +/* Synonyms */ +#define KERNEL_DS32 KERNEL_DS +#define USER_DS32 USER_DS + #ifdef __x86_64__ #define KERNEL_CS64 KERNEL_CS +#define USER_CS USER_CS64 #define KERNEL_DS64 KERNEL_DS -#define KERNEL_CS32 0x30 -#define KERNEL_DS32 0x38 -#define KERNEL_CS16 0x40 -#define KERNEL_DS16 0x48 +#define USER_DS64 USER_DS #else #define KERNEL_CS32 KERNEL_CS -#define KERNEL_DS32 KERNEL_DS +#define USER_CS USER_CS32 #endif -#define TSS_INTR 0x50 -#define FIRST_SPARE_SEL 0x58 + +#define FIRST_SPARE_SEL 0x50 #define TSS_MAIN 0x80 typedef struct { diff --git a/x86/cstart.S b/x86/cstart.S index 69b5c33..a3c26a4 100644 --- a/x86/cstart.S +++ b/x86/cstart.S @@ -34,14 +34,14 @@ gdt32: .quad 0x00cf9b000000ffff // flat 32-bit code segment .quad 0x00cf93000000ffff // flat 32-bit data segment .quad 0x00cf1b000000ffff // flat 32-bit code segment, not present - .quad 0x00cffb000000ffff // 64-bit code segment (user) - .quad 0x00cff3000000ffff // 64-bit data segment (user) - - .quad 0 // 10 spare selectors - .quad 0 - .quad 0 - .quad 0 - .quad 0 + .quad 0 // TSS for task gates + .quad 0x008f9b000000FFFF // 16-bit code segment + .quad 0x008f93000000FFFF // 16-bit data segment + .quad 0x00cffb000000ffff // 32-bit code segment (user) + .quad 0x00cff3000000ffff // 32-bit data segment (user) + .quad 0 // unused + + .quad 0 // 6 spare selectors .quad 0 .quad 0 .quad 0 diff --git a/x86/cstart64.S b/x86/cstart64.S index 004c014..4c26fb2 100644 --- a/x86/cstart64.S +++ b/x86/cstart64.S @@ -53,14 +53,14 @@ gdt64_desc: gdt64: .quad 0 .quad 0x00af9b000000ffff // 64-bit code segment - .quad 0x00cf93000000ffff // 64-bit data segment + .quad 0x00cf93000000ffff // 32/64-bit data segment .quad 0x00af1b000000ffff // 64-bit code segment, not present - .quad 0x00affb000000ffff // 64-bit code segment (user) - .quad 0x00cff3000000ffff // 64-bit data segment (user) .quad 0x00cf9b000000ffff // 32-bit code segment - .quad 0x00cf92000000ffff // 32-bit data segment - .quad 0x008F9A000000FFFF // 16-bit code segment - .quad 0x008F92000000FFFF // 16-bit data segment + .quad 0x008f9b000000FFFF // 16-bit code segment + .quad 0x008f93000000FFFF // 16-bit data segment + .quad 0x00cffb000000ffff // 32-bit code segment (user) + .quad 0x00cff3000000ffff // 32/64-bit data segment (user) + .quad 0x00affb000000ffff // 64-bit code segment (user) .quad 0 // 6 spare selectors .quad 0 -- 2.13.0