x86-qemu mpe cleanup
This commit is contained in:
parent
65e2c2c5dd
commit
3365c92c4b
|
@ -4,59 +4,65 @@
|
|||
|
||||
void readseg(unsigned char *, int, int);
|
||||
|
||||
struct boot_info {
|
||||
int is_ap;
|
||||
void (*entry)();
|
||||
};
|
||||
|
||||
void
|
||||
bootmain(void) {
|
||||
// multi-core boot hack, should use better ways.
|
||||
if (*(unsigned short*)(0x7c00 + 510) == 0x55aa) {
|
||||
((void(*)(void))*(void**)0x7010)();
|
||||
}
|
||||
struct ELFHeader *elf;
|
||||
struct ProgramHeader *ph, *eph;
|
||||
unsigned char *pa, *i;
|
||||
volatile struct boot_info *boot = (void*)0x7000;
|
||||
if (boot->is_ap) {
|
||||
boot->entry();
|
||||
}
|
||||
|
||||
elf = (struct ELFHeader*)0x8000;
|
||||
struct ELFHeader *elf;
|
||||
struct ProgramHeader *ph, *eph;
|
||||
unsigned char *pa, *i;
|
||||
|
||||
readseg((unsigned char*)elf, 4096, 0);
|
||||
elf = (struct ELFHeader*)0x8000;
|
||||
|
||||
ph = (struct ProgramHeader*)((char *)elf + elf->phoff);
|
||||
eph = ph + elf->phnum;
|
||||
for(; ph < eph; ph ++) {
|
||||
pa = (unsigned char*)(ph->paddr);
|
||||
readseg(pa, ph->filesz, ph->off);
|
||||
for (i = pa + ph->filesz; i < pa + ph->memsz; *i ++ = 0);
|
||||
}
|
||||
readseg((unsigned char*)elf, 4096, 0);
|
||||
|
||||
((void(*)(void))elf->entry)();
|
||||
ph = (struct ProgramHeader*)((char *)elf + elf->phoff);
|
||||
eph = ph + elf->phnum;
|
||||
for(; ph < eph; ph ++) {
|
||||
pa = (unsigned char*)(ph->paddr);
|
||||
readseg(pa, ph->filesz, ph->off);
|
||||
for (i = pa + ph->filesz; i < pa + ph->memsz; *i ++ = 0);
|
||||
}
|
||||
|
||||
((void(*)(void))elf->entry)();
|
||||
}
|
||||
|
||||
void
|
||||
waitdisk(void) {
|
||||
while ((in_byte(0x1F7) & 0xC0) != 0x40);
|
||||
while ((in_byte(0x1F7) & 0xC0) != 0x40);
|
||||
}
|
||||
|
||||
void
|
||||
readsect(volatile void *dst, int offset) {
|
||||
int i;
|
||||
waitdisk();
|
||||
out_byte(0x1F2, 1);
|
||||
out_byte(0x1F3, offset);
|
||||
out_byte(0x1F4, offset >> 8);
|
||||
out_byte(0x1F5, offset >> 16);
|
||||
out_byte(0x1F6, (offset >> 24) | 0xE0);
|
||||
out_byte(0x1F7, 0x20);
|
||||
int i;
|
||||
waitdisk();
|
||||
out_byte(0x1F2, 1);
|
||||
out_byte(0x1F3, offset);
|
||||
out_byte(0x1F4, offset >> 8);
|
||||
out_byte(0x1F5, offset >> 16);
|
||||
out_byte(0x1F6, (offset >> 24) | 0xE0);
|
||||
out_byte(0x1F7, 0x20);
|
||||
|
||||
waitdisk();
|
||||
for (i = 0; i < SECTSIZE / 4; i ++) {
|
||||
((int *)dst)[i] = in_long(0x1F0);
|
||||
}
|
||||
waitdisk();
|
||||
for (i = 0; i < SECTSIZE / 4; i ++) {
|
||||
((int *)dst)[i] = in_long(0x1F0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
readseg(unsigned char *pa, int count, int offset) {
|
||||
unsigned char *epa;
|
||||
epa = pa + count;
|
||||
pa -= offset % SECTSIZE;
|
||||
offset = (offset / SECTSIZE) + 1;
|
||||
for(; pa < epa; pa += SECTSIZE, offset ++)
|
||||
readsect(pa, offset);
|
||||
unsigned char *epa;
|
||||
epa = pa + count;
|
||||
pa -= offset % SECTSIZE;
|
||||
offset = (offset / SECTSIZE) + 1;
|
||||
for(; pa < epa; pa += SECTSIZE, offset ++)
|
||||
readsect(pa, offset);
|
||||
}
|
||||
|
|
|
@ -10,14 +10,14 @@ _start:
|
|||
movw %ax, %ss
|
||||
|
||||
# Set a 640 x 480 x 32 video mode
|
||||
mov $0x4f01, %ax
|
||||
mov $0x0112, %cx
|
||||
mov $0x4000, %di
|
||||
int $0x10
|
||||
mov $0x4f01, %ax
|
||||
mov $0x0112, %cx
|
||||
mov $0x4000, %di
|
||||
int $0x10
|
||||
|
||||
mov $0x4f02, %ax
|
||||
mov $0x4112, %bx
|
||||
int $0x10
|
||||
mov $0x4f02, %ax
|
||||
mov $0x4112, %bx
|
||||
int $0x10
|
||||
|
||||
lgdt gdtdesc
|
||||
movl %cr0, %eax
|
||||
|
@ -32,9 +32,7 @@ start32:
|
|||
movw %ax, %es
|
||||
movw %ax, %ss
|
||||
|
||||
movl (0x7020), %esp # multi-core hack
|
||||
# M[0x7020] is the core's bootstrap stack offset
|
||||
addl $0x2000, %esp
|
||||
movl $0x7000, %esp
|
||||
call bootmain
|
||||
|
||||
# GDT
|
||||
|
@ -46,4 +44,4 @@ gdt:
|
|||
|
||||
gdtdesc:
|
||||
.word (gdtdesc - gdt - 1)
|
||||
.long gdt
|
||||
.long gdt
|
||||
|
|
|
@ -5,15 +5,14 @@ static void (* volatile user_entry)();
|
|||
static intptr_t apboot_done = 0;
|
||||
|
||||
static void mp_entry();
|
||||
|
||||
static uint8_t cpu_stk[MAX_CPU][4096];
|
||||
static void call_switch_stk(void (*entry)());
|
||||
static void stack_switch(void (*entry)());
|
||||
|
||||
int _mpe_init(void (*entry)()) {
|
||||
user_entry = entry;
|
||||
|
||||
call_switch_stk(mp_entry);
|
||||
return 0; // never reaches here
|
||||
stack_switch(mp_entry); // switch stack, and the bootstrap stack at
|
||||
// 0x7000 can be reused by an ap's bootloader
|
||||
panic("mp_init should not return");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _cpu(void) {
|
||||
|
@ -26,12 +25,17 @@ int _ncpu() {
|
|||
|
||||
intptr_t _atomic_xchg(volatile intptr_t *addr, intptr_t newval) {
|
||||
intptr_t result;
|
||||
asm volatile("lock; xchgl %0, %1":
|
||||
asm volatile("lock xchgl %0, %1":
|
||||
"+m"(*addr), "=a"(result): "1"(newval): "cc");
|
||||
return result;
|
||||
}
|
||||
|
||||
void ap_init() {
|
||||
struct boot_info {
|
||||
int is_ap;
|
||||
void (*entry)();
|
||||
};
|
||||
|
||||
static void ap_entry() {
|
||||
cpu_initgdt();
|
||||
lapic_init();
|
||||
ioapic_enable(IRQ_KBD, _cpu());
|
||||
|
@ -40,27 +44,26 @@ void ap_init() {
|
|||
user_entry();
|
||||
}
|
||||
|
||||
#include <klib.h>
|
||||
static void stack_switch(void (*entry)()) {
|
||||
static uint8_t cpu_stk[MAX_CPU][4096]; // each cpu gets a 4KB stack
|
||||
asm volatile(
|
||||
"movl %0, %%esp;"
|
||||
"call *%1" : : "r"(&cpu_stk[_cpu() + 1][0]), "r"(entry));
|
||||
}
|
||||
|
||||
static void mp_entry() {
|
||||
static void mp_entry() { // all cpus execute mp_entry()
|
||||
if (_cpu() != 0) {
|
||||
call_switch_stk(ap_init);
|
||||
// init an ap
|
||||
stack_switch(ap_entry);
|
||||
} else {
|
||||
// stack already swithced, boot all aps
|
||||
volatile struct boot_info *boot = (void *)0x7000;
|
||||
for (int cpu = 1; cpu < ncpu; cpu ++) {
|
||||
*(uint16_t*)(0x7c00 + 510) = 0x55aa;
|
||||
*(uint32_t*)(0x7000) = 0x007c00ea; // code for ljmp
|
||||
*(uint32_t*)(0x7004) = 0x00000000;
|
||||
*(void**)(0x7010) = (void*)mp_entry;
|
||||
*(uint32_t*)(0x7020) = 0x4000; // 1KB bootstrap stack
|
||||
lapic_bootap(cpu, 0x7000);
|
||||
boot->is_ap = 1;
|
||||
boot->entry = mp_entry;
|
||||
lapic_bootap(cpu, 0x7c00);
|
||||
while (_atomic_xchg(&apboot_done, 0) != 1);
|
||||
}
|
||||
user_entry();
|
||||
}
|
||||
}
|
||||
|
||||
static void call_switch_stk(void (*entry)()) {
|
||||
asm volatile (
|
||||
"movl %0, %%esp;"
|
||||
"call *%1" : : "r"(&cpu_stk[_cpu() + 1][0]), "r"(entry));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue