This commit is contained in:
Yanyan Jiang 2020-02-01 12:28:30 +00:00
parent 364f12191c
commit 1fa0d8e663
8 changed files with 102 additions and 106 deletions

View File

@ -24,6 +24,7 @@
#define PTE_P 0x001 // Present
#define PTE_W 0x002 // Writeable
#define PTE_U 0x004 // User
#define PTE_PS 0x080 // Large Page (1 GiB or 2 MiB)
// GDT entries
#define NR_SEG 6 // GDT size
@ -95,6 +96,11 @@
_( 47, KERN, NOERR) \
_(128, USER, NOERR)
// AM-specific configurations
#define MAX_CPU 8
#define BOOTREC_ADDR 0x07000
#define MAINARG_ADDR 0x10000
// Below are only visible to c/cpp files
#ifndef __ASSEMBLER__
@ -102,40 +108,21 @@
// Segment Descriptor
typedef struct {
uint32_t lim_15_0 : 16; // Low bits of segment limit
uint32_t base_15_0 : 16; // Low bits of segment base address
uint32_t base_23_16 : 8; // Middle bits of segment base address
uint32_t type : 4 ; // Segment type (see STS_ constants)
uint32_t s : 1; // 0 = system, 1 = application
uint32_t dpl : 2; // Descriptor Privilege Level
uint32_t p : 1; // Present
uint32_t lim_19_16 : 4; // High bits of segment limit
uint32_t avl : 1; // Unused (available for software use)
uint32_t l : 1; // 1 = 64-bit
uint32_t db : 1; // 0 = 16-bit segment, 1 = 32-bit segment
uint32_t g : 1; // Granularity: limit scaled by 4K when set
uint32_t base_31_24 : 8; // High bits of segment base address
uint32_t lim_15_0 : 16; // Low bits of segment limit
uint32_t base_15_0 : 16; // Low bits of segment base address
uint32_t base_23_16 : 8; // Middle bits of segment base address
uint32_t type : 4; // Segment type (see STS_ constants)
uint32_t s : 1; // 0 = system, 1 = application
uint32_t dpl : 2; // Descriptor Privilege Level
uint32_t p : 1; // Present
uint32_t lim_19_16 : 4; // High bits of segment limit
uint32_t avl : 1; // Unused (available for software use)
uint32_t l : 1; // 64-bit segment
uint32_t db : 1; // 32-bit segment
uint32_t g : 1; // Granularity: limit scaled by 4K when set
uint32_t base_31_24 : 8; // High bits of segment base address
} SegDesc;
#define SEG16(type, base, lim, dpl) (SegDesc) \
{ (lim) & 0xffff, (uintptr_t)(base) & 0xffff, \
((uintptr_t)(base) >> 16) & 0xff, type, 0, dpl, 1, \
(uintptr_t)(lim) >> 16, 0, 0, 1, 0, (uintptr_t)(base) >> 24 }
#define SEG32(type, base, lim, dpl) (SegDesc) \
{ ((lim) >> 12) & 0xffff, (uintptr_t)(base) & 0xffff, \
((uintptr_t)(base) >> 16) & 0xff, type, 1, dpl, 1, \
(uintptr_t)(lim) >> 28, 0, 0, 1, 1, (uintptr_t)(base) >> 24 }
#define SEG64(type, dpl) (SegDesc) \
{ 0, 0, 0, type, 1, dpl, 1, 0, 0, 1, 0, 0 }
#define SEGTSS64(type, base, lim, dpl) (SegDesc) \
{ (lim) & 0xffff, (uint32_t)(base) & 0xffff, \
((uint32_t)(base) >> 16) & 0xff, type, 0, dpl, 1, \
(uint32_t)(lim) >> 16, 0, 0, 0, 0, (uint32_t)(base) >> 24 }
// Gate descriptors for interrupts and traps
typedef struct {
uint32_t off_15_0 : 16; // Low 16 bits of offset in segment
@ -149,10 +136,6 @@ typedef struct {
uint32_t off_31_16 : 16; // High bits of offset in segment
} GateDesc32;
#define GATE32(type, cs, entry, dpl) (GateDesc32) \
{ (uint32_t)(entry) & 0xffff, (cs), 0, 0, (type), 0, (dpl), \
1, (uint32_t)(entry) >> 16 }
typedef struct {
uint32_t off_15_0 : 16;
uint32_t cs : 16;
@ -167,11 +150,7 @@ typedef struct {
uint32_t rsv : 32;
} GateDesc64;
#define GATE64(type, cs, entry, dpl) (GateDesc64) \
{ (uint64_t)(entry) & 0xffff, (cs), 0, 0, (type), 0, (dpl), \
1, ((uint64_t)(entry) >> 16) & 0xffff, (uint64_t)(entry) >> 32, 0 }
// Task state segment format
// Task State Segment (TSS)
typedef struct {
uint32_t link; // Unused
uint32_t esp0; // Stack pointers and segment selectors
@ -212,7 +191,36 @@ typedef struct {
uint8_t reserved[3];
} MPDesc;
#define asm __asm__
typedef struct {
uint32_t jmp_code;
int32_t is_ap;
} BootRecord;
#define SEG16(type, base, lim, dpl) (SegDesc) \
{ (lim) & 0xffff, (uintptr_t)(base) & 0xffff, \
((uintptr_t)(base) >> 16) & 0xff, type, 0, dpl, 1, \
(uintptr_t)(lim) >> 16, 0, 0, 1, 0, (uintptr_t)(base) >> 24 }
#define SEG32(type, base, lim, dpl) (SegDesc) \
{ ((lim) >> 12) & 0xffff, (uintptr_t)(base) & 0xffff, \
((uintptr_t)(base) >> 16) & 0xff, type, 1, dpl, 1, \
(uintptr_t)(lim) >> 28, 0, 0, 1, 1, (uintptr_t)(base) >> 24 }
#define SEG64(type, dpl) (SegDesc) \
{ 0, 0, 0, type, 1, dpl, 1, 0, 0, 1, 0, 0 }
#define SEGTSS64(type, base, lim, dpl) (SegDesc) \
{ (lim) & 0xffff, (uint32_t)(base) & 0xffff, \
((uint32_t)(base) >> 16) & 0xff, type, 0, dpl, 1, \
(uint32_t)(lim) >> 16, 0, 0, 0, 0, (uint32_t)(base) >> 24 }
#define GATE32(type, cs, entry, dpl) (GateDesc32) \
{ (uint32_t)(entry) & 0xffff, (cs), 0, 0, (type), 0, (dpl), \
1, (uint32_t)(entry) >> 16 }
#define GATE64(type, cs, entry, dpl) (GateDesc64) \
{ (uint64_t)(entry) & 0xffff, (cs), 0, 0, (type), 0, (dpl), \
1, ((uint64_t)(entry) >> 16) & 0xffff, (uint64_t)(entry) >> 32, 0 }
static inline uint8_t inb(int port) {
uint8_t data;
@ -326,4 +334,8 @@ static inline void stack_switch_call(void *sp, void *entry, uintptr_t arg) {
);
}
static inline volatile BootRecord *boot_record() {
return (BootRecord *)BOOTREC_ADDR;
}
#endif // __ASSEMBLER__

View File

@ -70,7 +70,7 @@ void load_kernel(void) {
if (!is_ap) {
// load argument (string) to memory
copy_from_disk((void *)ARG_ADDR, 1024, -1024);
copy_from_disk((void *)MAINARG_ADDR, 1024, -1024);
// load elf header to memory
copy_from_disk(elf32, 4096, 0);
if (elf32->e_machine == EM_X86_64) {

View File

@ -355,14 +355,14 @@ void __am_lapic_eoi(void) {
lapicw(EOI, 0);
}
void __am_lapic_bootap(uint32_t apicid, uint32_t addr) {
void __am_lapic_bootap(uint32_t apicid, void *addr) {
int i;
uint16_t *wrv;
outb(0x70, 0xF);
outb(0x71, 0x0A);
wrv = (unsigned short*)((0x40<<4 | 0x67));
wrv[0] = 0;
wrv[1] = addr >> 4;
wrv[1] = (uintptr_t)addr >> 4;
lapicw(ICRHI, apicid<<24);
lapicw(ICRLO, INIT | LEVEL | ASSERT);
@ -370,7 +370,7 @@ void __am_lapic_bootap(uint32_t apicid, uint32_t addr) {
for (i = 0; i < 2; i++){
lapicw(ICRHI, apicid<<24);
lapicw(ICRLO, STARTUP | (addr>>12));
lapicw(ICRLO, STARTUP | ((uintptr_t)addr>>12));
}
}

View File

@ -14,7 +14,7 @@ int _mpe_init(void (*entry)()) {
boot_record()->jmp_code = 0x000bfde9; // (16-bit) jmp (0x7c00)
for (int cpu = 1; cpu < __am_ncpu; cpu++) {
boot_record()->is_ap = 1;
__am_lapic_bootap(cpu, BOOT_REC_ADDR);
__am_lapic_bootap(cpu, (void *)boot_record());
while (_atomic_xchg(&ap_ready, 0) != 1) {
pause();
}
@ -52,7 +52,7 @@ void __am_stop_the_world() {
boot_record()->jmp_code = 0x0000feeb; // (16-bit) jmp .
for (int cpu = 0; cpu < __am_ncpu; cpu++) {
if (cpu != _cpu()) {
__am_lapic_bootap(cpu, BOOT_REC_ADDR);
__am_lapic_bootap(cpu, (void *)boot_record());
}
}
}

View File

@ -3,6 +3,6 @@
.globl _start
_start:
pushl $ARG_ADDR
pushl $MAINARG_ADDR
pushl $0
jmp _start_c

View File

@ -4,59 +4,56 @@
.code32
.globl _start
_start:
#define PML4 0x1000
#define PDPT 0x2000
movl $PDPT_ADDR + 3, %eax
cmpl (PML4_ADDR), %eax
je .long_mode_init
movl $PDPT + 3, %eax
cmpl (PML4), %eax
je .long_mode_init
movl $PDPT_ADDR + 3, %eax
movl %eax, (PML4_ADDR)
movl $PDPT + 3, %eax
movl %eax, (PML4)
movl $0, %ecx
movl $512, %esi // 512 pages
// |
.loop: // x
movl %ecx, %eax // |
shll $30, %eax // |
orl $(PTE_P | PTE_PS | PTE_W), %eax // 1 GiB page
movl %eax, PDPT_ADDR(, %ecx, 8)
movl $0, %ecx
movl $512, %esi // 512 pages
// |
.loop: // x
movl %ecx, %eax // |
shll $30, %eax // |
orl $0x83, %eax // 1 GiB page
movl %eax, PDPT(, %ecx, 8)
movl %ecx, %eax
shrl $2, %eax
movl %eax, PDPT_ADDR + 4(, %ecx, 8)
movl %ecx, %eax
shrl $2, %eax
movl %eax, PDPT + 4(, %ecx, 8)
inc %ecx
cmp %esi, %ecx
jne .loop
inc %ecx
cmp %esi, %ecx
jne .loop
.long_mode_init:
movl $PML4, %eax
movl %eax, %cr3 // %cr3 = PML4 base
movl $0x80000021, %eax
movl %eax, %cr4 // %cr4.PAE = 1
movl $0xc0000080, %ecx
movl $PML4_ADDR, %eax
movl %eax, %cr3 // %cr3 = PML4 base
movl $0x80000021, %eax
movl %eax, %cr4 // %cr4.PAE = 1
movl $0xc0000080, %ecx
rdmsr
orl $0x100, %eax
orl $0x100, %eax
wrmsr // %msr.LME = 1.
movl $0x80000011, %eax
movl %eax, %cr0 // %cr0.PG = 1, %cr0.PE = 1
lgdt gdt_ptr // bootstrap GDT
ljmp $8, $_start64 // should not return
movl $0x80000011, %eax
movl %eax, %cr0 // %cr0.PG = 1, %cr0.PE = 1
lgdt gdt_ptr // bootstrap GDT
ljmp $8, $_start64 // should not return
.code64
_start64:
movw $0, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movw %ax, %fs
movw %ax, %gs
movw $0, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movw %ax, %fs
movw %ax, %gs
movq $ARG_ADDR, %rdi
movq $MAINARG_ADDR, %rdi
pushq $0
jmp _start_c
jmp _start_c
.align 16
gdt_ptr:

View File

@ -92,7 +92,7 @@ int _vme_init(void *(*_pgalloc)(size_t size), void (*_pgfree)(void *)) {
pgfree = _pgfree;
#if __x86_64__
kpt = (void *)0x1000;
kpt = (void *)PML4_ADDR;
#else
_AddressSpace as;
as.ptr = NULL;

View File

@ -1,6 +1,5 @@
#define MAX_CPU 8
#define BOOT_REC_ADDR 0x07000
#define ARG_ADDR 0x10000
#define PML4_ADDR 0x1000
#define PDPT_ADDR 0x2000
#ifndef __ASSEMBLER__
@ -11,18 +10,6 @@
#define ROUNDUP(a, sz) ((((uintptr_t)a)+(sz)-1) & ~((sz)-1))
#define ROUNDDOWN(a, sz) ((((uintptr_t)a)) & ~((sz)-1))
struct boot_record {
uint32_t jmp_code;
int32_t is_ap;
};
static inline volatile struct boot_record *boot_record() {
return (struct boot_record *)BOOT_REC_ADDR;
}
void bootcpu_init();
_Area memory_probe();
struct kernel_stack {
uint8_t stack[8192];
};
@ -114,7 +101,7 @@ static inline void puts(const char *s) {
// apic utils
void __am_lapic_eoi();
void __am_ioapic_init();
void __am_lapic_bootap(uint32_t cpu, uint32_t address);
void __am_lapic_bootap(uint32_t cpu, void *address);
void __am_ioapic_enable(int irq, int cpu);
// x86-specific operations