x86: add GDT generator tool
This commit is contained in:
parent
21798e1396
commit
205326bccd
2 changed files with 135 additions and 0 deletions
arch/x86/tools
1
arch/x86/tools/.gitignore
vendored
Normal file
1
arch/x86/tools/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
./gdt
|
134
arch/x86/tools/gdt.c
Normal file
134
arch/x86/tools/gdt.c
Normal file
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* This program generates the GDT entries for the x86.
|
||||
* Taken from <https://wiki.osdev.org/GDT_Tutorial> and modified to our needs.
|
||||
* It conforms to ISO C99 and can be built on any POSIX compliant system using
|
||||
* the command `make gdt.c`. It outputs the assembly directives for the GDT.
|
||||
*
|
||||
* May nobody need to touch this mess ever again.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* Each define here is for a specific flag in the descriptor.
|
||||
* See the Intel SDM vol 3A, sec 3.4, fig 3-8 for details.
|
||||
*/
|
||||
#define SEG_TYPE(x) ((x) << 12) /* Descriptor type (0 for system, 1 for code/data) */
|
||||
#define SEG_PRIV(x) (((x) & 3) << 13) /* Descriptor Privilege Level (0 - 3) */
|
||||
#define SEG_PRES(x) ((x) << 15) /* Present */
|
||||
#define SEG_AVL(x) ((x) << 20) /* Available for system use (we don't use that) */
|
||||
#define SEG_LONG(x) ((x) << 21) /* 64-bit Long mode code segment */
|
||||
#define SEG_SIZE(x) ((x) << 22) /* Size (0 for 16/64-bit, 1 for 32) */
|
||||
#define SEG_GRAN(x) ((x) << 23) /* Granularity (0 for 1B - 1MB, 1 for 4KB - 4GB) */
|
||||
|
||||
#define SEG_DATA_R 0x000 /* read */
|
||||
#define SEG_DATA_RA 0x100 /* read, accessed */
|
||||
#define SEG_DATA_RW 0x200 /* read, write */
|
||||
#define SEG_DATA_RWA 0x300 /* read, write, accessed */
|
||||
#define SEG_DATA_RE 0x400 /* read, expand-down */
|
||||
#define SEG_DATA_REA 0x500 /* read, expand-down, accessed */
|
||||
#define SEG_DATA_REW 0x600 /* read, write */
|
||||
#define SEG_DATA_REWA 0x700 /* read, expand-down, write, accessed */
|
||||
|
||||
#define SEG_CODE_X 0x800 /* execute */
|
||||
#define SEG_CODE_XA 0x900 /* execute, accessed */
|
||||
#define SEG_CODE_XR 0xa00 /* execute, read */
|
||||
#define SEG_CODE_XRA 0xb00 /* execute, read, accessed */
|
||||
#define SEG_CODE_XC 0xc00 /* execute, conforming */
|
||||
#define SEG_CODE_XCA 0xd00 /* execute, conforming, accessed */
|
||||
#define SEG_CODE_XCR 0xe00 /* execute, conforming, read */
|
||||
#define SEG_CODE_XCRA 0xf00 /* execute, conforming, read, accessed */
|
||||
|
||||
#define KERN_CODE32 ( \
|
||||
SEG_TYPE(1) | SEG_PRES(1) | SEG_AVL(0) | \
|
||||
SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \
|
||||
SEG_PRIV(0) | SEG_CODE_XR \
|
||||
)
|
||||
|
||||
#define USER_CODE32 ( \
|
||||
SEG_TYPE(1) | SEG_PRES(1) | SEG_AVL(0) | \
|
||||
SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \
|
||||
SEG_PRIV(3) | SEG_CODE_XR \
|
||||
)
|
||||
|
||||
#define KERN_CODE64 ( \
|
||||
SEG_TYPE(1) | SEG_PRES(1) | SEG_AVL(0) | \
|
||||
SEG_LONG(1) | SEG_SIZE(0) | SEG_GRAN(1) | \
|
||||
SEG_PRIV(0) | SEG_CODE_XR \
|
||||
)
|
||||
|
||||
#define USER_CODE64 ( \
|
||||
SEG_TYPE(1) | SEG_PRES(1) | SEG_AVL(0) | \
|
||||
SEG_LONG(1) | SEG_SIZE(0) | SEG_GRAN(1) | \
|
||||
SEG_PRIV(3) | SEG_CODE_XR \
|
||||
)
|
||||
|
||||
#define KERN_DATA ( \
|
||||
SEG_TYPE(1) | SEG_PRES(1) | SEG_AVL(0) | \
|
||||
SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \
|
||||
SEG_PRIV(0) | SEG_DATA_RW \
|
||||
)
|
||||
|
||||
#define USER_DATA ( \
|
||||
SEG_TYPE(1) | SEG_PRES(1) | SEG_AVL(0) | \
|
||||
SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \
|
||||
SEG_PRIV(3) | SEG_DATA_RW \
|
||||
)
|
||||
|
||||
#define KERN_TSS ( \
|
||||
SEG_TYPE(0) | SEG_PRES(1) | SEG_AVL(0) | \
|
||||
SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(0) | \
|
||||
SEG_PRIV(0) | SEG_CODE_XA \
|
||||
)
|
||||
|
||||
#define USER_TSS ( \
|
||||
SEG_TYPE(0) | SEG_PRES(1) | SEG_AVL(0) | \
|
||||
SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(0) | \
|
||||
SEG_PRIV(3) | SEG_CODE_XA \
|
||||
)
|
||||
|
||||
int offset(void)
|
||||
{
|
||||
static int i = 0;
|
||||
return i++ * 8;
|
||||
}
|
||||
|
||||
void print_desc(uint32_t base, uint32_t limit, uint32_t flag, const char *comment)
|
||||
{
|
||||
uint32_t low_desc, high_desc;
|
||||
|
||||
/* Create the low 32 bit segment part */
|
||||
low_desc = base << 16; /* set base bits 15:0 */
|
||||
low_desc |= limit & 0x0000FFFF; /* set limit bits 15:0 */
|
||||
|
||||
/* Create the high 32 bit segment part */
|
||||
high_desc = limit & 0x000F0000; /* set limit bits 19:16 */
|
||||
high_desc |= flag & 0x00F0FF00; /* set type, p, dpl, s, g, d/b, l and avl fields */
|
||||
high_desc |= (base >> 16) & 0x000000FF; /* set base bits 23:16 */
|
||||
high_desc |= base & 0xFF000000; /* set base bits 31:24 */
|
||||
|
||||
printf("\t.quad 0x%08"PRIx32"%08"PRIx32" /* 0x%02x %s */\n",
|
||||
high_desc, low_desc, offset(), comment);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
print_desc(0, 0x00000000, 0, "null descriptor ");
|
||||
print_desc(0, 0x00000000, 0, "unused ");
|
||||
print_desc(0, 0x000fffff, KERN_CODE32, "kernel code 32-bit");
|
||||
print_desc(0, 0x000fffff, USER_CODE32, "user code 32-bit");
|
||||
print_desc(0, 0x000fffff, KERN_CODE64, "kernel code 64-bit");
|
||||
print_desc(0, 0x000fffff, USER_CODE64, "user code 64-bit");
|
||||
print_desc(0, 0x000fffff, KERN_DATA, "kernel data ");
|
||||
print_desc(0, 0x000fffff, USER_DATA, "user data ");
|
||||
/* the TSS bases are initialized dynamically in arch/x86/boot/setup{32,64}.S */
|
||||
print_desc(0, 0x00000068, KERN_TSS, "kernel TSS ");
|
||||
print_desc(0, 0x00000000, 0, " .. pad for 64-bit");
|
||||
print_desc(0, 0x00000068, USER_TSS, "user TSS ");
|
||||
print_desc(0, 0x00000000, 0, " .. pad for 64-bit");
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue