x86-qemu mpe cleanup

This commit is contained in:
Yanyan Jiang 2018-08-09 08:02:39 +00:00
parent 65e2c2c5dd
commit 3365c92c4b
3 changed files with 77 additions and 70 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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));
}