You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
4.9 KiB
C
135 lines
4.9 KiB
C
/*
|
|
* 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;
|
|
}
|