refactor
This commit is contained in:
parent
364f12191c
commit
1fa0d8e663
|
@ -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__
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,6 @@
|
|||
|
||||
.globl _start
|
||||
_start:
|
||||
pushl $ARG_ADDR
|
||||
pushl $MAINARG_ADDR
|
||||
pushl $0
|
||||
jmp _start_c
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue