x86-qemu, makefiles: simplify ld commands
This commit is contained in:
parent
38a7ad8ed9
commit
6102652dc8
10
Makefile.app
10
Makefile.app
|
@ -14,11 +14,13 @@ INC_DIR += $(addsuffix /include/, $(addprefix $(AM_HOME)/libs/, $(LIBS)))
|
|||
|
||||
include $(AM_HOME)/Makefile.compile
|
||||
|
||||
LINK_LIBS += $(LIBS)
|
||||
LINK_FILES += $(AM_HOME)/am/build/am-$(ARCH).a $(OBJS) \
|
||||
LINK_LIBS = $(LIBS)
|
||||
LINK_FILES = \
|
||||
$(OBJS) \
|
||||
$(AM_HOME)/am/build/am-$(ARCH).a \
|
||||
$(addsuffix -$(ARCH).a, $(join \
|
||||
$(addsuffix /build/, $(addprefix $(AM_HOME)/libs/, $(LINK_LIBS))), \
|
||||
$(LINK_LIBS) \
|
||||
$(addsuffix /build/, $(addprefix $(AM_HOME)/libs/, $(LINK_LIBS))), \
|
||||
$(LINK_LIBS) \
|
||||
))
|
||||
|
||||
$(OBJS): $(PREBUILD)
|
||||
|
|
|
@ -15,7 +15,8 @@ include $(AM_HOME)/Makefile.compile
|
|||
|
||||
$(ARCHIVE): $(OBJS)
|
||||
@echo + AR "->" $(shell realpath $@ --relative-to .)
|
||||
@ar rcs $(ARCHIVE) $(OBJS)
|
||||
# @ar rcs $(ARCHIVE) $(OBJS)
|
||||
@ld -r -o $(ARCHIVE) $(LDFLAGS) $(OBJS)
|
||||
|
||||
clean:
|
||||
rm -rf $(LIB_DIR)/build/
|
||||
|
|
|
@ -13,7 +13,7 @@ ASFLAGS += -fpie -pie
|
|||
|
||||
image:
|
||||
@echo + LD "->" $(BINARY_REL)
|
||||
@g++ -pie -o $(BINARY) -Wl,--start-group $(LINK_FILES) -Wl,--end-group -lSDL2 -lGL -lrt
|
||||
@g++ -pie -o $(BINARY) $(LINK_FILES) -lSDL2 -lGL -lrt
|
||||
|
||||
run:
|
||||
$(BINARY)
|
||||
|
|
|
@ -12,7 +12,7 @@ LD_SCRIPT := $(AM_HOME)/am/src/$(ISA)/nemu/boot/loader.ld
|
|||
|
||||
image:
|
||||
@echo + LD "->" $(BINARY_REL).elf
|
||||
@$(LD) $(LDFLAGS) --gc-sections -T $(LD_SCRIPT) -e _start -o $(BINARY).elf --start-group $(LINK_FILES) --end-group
|
||||
@$(LD) $(LDFLAGS) --gc-sections -T $(LD_SCRIPT) -e _start -o $(BINARY).elf $(LINK_FILES)
|
||||
@$(OBJDUMP) -d $(BINARY).elf > $(BINARY).txt
|
||||
@echo + OBJCOPY "->" $(BINARY_REL).bin
|
||||
@$(OBJCOPY) -S --set-section-flags .bss=alloc,contents -O binary $(BINARY).elf $(BINARY).bin
|
||||
|
|
|
@ -17,7 +17,7 @@ AM_SRCS := x86/qemu/trm.c \
|
|||
image:
|
||||
@make -s -C $(AM_HOME)/am/src/x86/qemu/boot
|
||||
@echo + LD "->" $(BINARY_REL).o
|
||||
@$(LD) $(LDFLAGS) -Ttext 0x00100000 -o $(BINARY).o --start-group $(LINK_FILES) --end-group
|
||||
@$(LD) $(LDFLAGS) -Ttext 0x00100000 -o $(BINARY).o $(LINK_FILES)
|
||||
@echo + CREATE "->" $(BINARY_REL)
|
||||
@cat $(AM_HOME)/am/src/x86/qemu/boot/mbr $(BINARY).o > $(BINARY)
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ int cte_init(_Context *(*handler)(_Event, _Context *)) {
|
|||
IRQS(IDT_ENTRY)
|
||||
|
||||
user_handler = handler;
|
||||
percpu_initirq();
|
||||
__am_percpu_initirq();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ _Context *kcontext(_Area stack, void (*entry)(void *), void *arg) {
|
|||
|
||||
void *values[] = { panic_on_return, arg }; // copy to stack
|
||||
ctx->esp0 -= sizeof(values);
|
||||
for (int i = 0; i < NELEM(values); i++) {
|
||||
for (int i = 0; i < LENGTH(values); i++) {
|
||||
((uintptr_t *)ctx->esp0)[i] = (uintptr_t)values[i];
|
||||
}
|
||||
return ctx;
|
||||
|
@ -72,7 +72,7 @@ _Context *_cb_irq(_Event ev, _Context *ctx) {
|
|||
return user_handler(ev, ctx);
|
||||
}
|
||||
|
||||
void irq_handle(TrapFrame *tf) {
|
||||
void __am_irq_handle(TrapFrame *tf) {
|
||||
// saving processor context
|
||||
_Context ctx = {
|
||||
.eax = tf->eax, .ebx = tf->ebx, .ecx = tf->ecx, .edx = tf->edx,
|
||||
|
@ -93,7 +93,7 @@ void irq_handle(TrapFrame *tf) {
|
|||
|
||||
// sending end-of-interrupt
|
||||
if (IRQ 0 <= tf->irq && tf->irq < IRQ 32) {
|
||||
lapic_eoi();
|
||||
__am_lapic_eoi();
|
||||
}
|
||||
|
||||
// creating an event
|
||||
|
@ -169,7 +169,7 @@ void irq_handle(TrapFrame *tf) {
|
|||
if (prot) {
|
||||
set_cr3(prot->ptr);
|
||||
}
|
||||
thiscpu_setstk0(ret_ctx->ss0, ret_ctx->esp0);
|
||||
__am_thiscpu_setstk0(ret_ctx->ss0, ret_ctx->esp0);
|
||||
asm volatile goto (
|
||||
"movl %[esp], %%esp;" // move stack
|
||||
REGS_USER(push) // push reg context onto stack
|
||||
|
@ -193,9 +193,9 @@ iret:
|
|||
);
|
||||
}
|
||||
|
||||
void percpu_initirq() {
|
||||
void __am_percpu_initirq() {
|
||||
if (user_handler) {
|
||||
ioapic_enable(IRQ_KBD, 0);
|
||||
__am_ioapic_enable(IRQ_KBD, 0);
|
||||
set_idt(idt, sizeof(idt));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ trap:
|
|||
movw %ax, %es
|
||||
|
||||
pushl %esp
|
||||
call irq_handle // iret in the C code
|
||||
call __am_irq_handle // iret in the C code
|
||||
|
||||
#define NOERR pushl $0
|
||||
#define ERR
|
||||
|
|
|
@ -37,23 +37,47 @@
|
|||
#define TCCR (0x0390/4) // Timer Current Count
|
||||
#define TDCR (0x03E0/4) // Timer Divide Configuration
|
||||
|
||||
volatile unsigned int *lapic; // Initialized in mp.c
|
||||
// The I/O APIC manages hardware interrupts for an SMP system.
|
||||
// http://www.intel.com/design/chipsets/datashts/29056601.pdf
|
||||
// See also picirq.c.
|
||||
#define IOAPIC_ADDR 0xFEC00000 // Default physical address of IO APIC
|
||||
#define REG_ID 0x00 // Register index: ID
|
||||
#define REG_VER 0x01 // Register index: version
|
||||
#define REG_TABLE 0x10 // Redirection table base
|
||||
|
||||
// The redirection table starts at REG_TABLE and uses
|
||||
// two registers to configure each interrupt.
|
||||
// The first (low) register in a pair contains configuration bits.
|
||||
// The second (high) register contains a bitmask telling which
|
||||
// CPUs can serve that interrupt.
|
||||
#define INT_DISABLED 0x00010000 // Interrupt disabled
|
||||
#define INT_LEVEL 0x00008000 // Level-triggered (vs edge-)
|
||||
#define INT_ACTIVELOW 0x00002000 // Active low (vs high)
|
||||
#define INT_LOGICAL 0x00000800 // Destination is CPU id (vs APIC ID)
|
||||
|
||||
volatile unsigned int *__am_lapic; // Initialized in mp.c
|
||||
struct IOAPIC {
|
||||
uint32_t reg, pad[3], data;
|
||||
};
|
||||
typedef struct IOAPIC IOAPIC;
|
||||
|
||||
static volatile IOAPIC *ioapic;
|
||||
|
||||
static void
|
||||
lapicw(int index, int value)
|
||||
{
|
||||
lapic[index] = value;
|
||||
lapic[ID]; // wait for write to finish, by reading
|
||||
__am_lapic[index] = value;
|
||||
__am_lapic[ID]; // wait for write to finish, by reading
|
||||
}
|
||||
|
||||
void
|
||||
percpu_initlapic(void)
|
||||
__am_percpu_initlapic(void)
|
||||
{
|
||||
// Enable local APIC; set spurious interrupt vector.
|
||||
lapicw(SVR, ENABLE | (T_IRQ0 + IRQ_SPURIOUS));
|
||||
|
||||
// The timer repeatedly counts down at bus frequency
|
||||
// from lapic[TICR] and then issues an interrupt.
|
||||
// from __am_lapic[TICR] and then issues an interrupt.
|
||||
// If xv6 cared more about precise timekeeping,
|
||||
// TICR would be calibrated using an external time source.
|
||||
lapicw(TDCR, X1);
|
||||
|
@ -66,7 +90,7 @@ percpu_initlapic(void)
|
|||
|
||||
// Disable performance counter overflow interrupts
|
||||
// on machines that provide that interrupt entry.
|
||||
if(((lapic[VER]>>16) & 0xFF) >= 4)
|
||||
if(((__am_lapic[VER]>>16) & 0xFF) >= 4)
|
||||
lapicw(PCINT, MASKED);
|
||||
|
||||
// Map error interrupt to IRQ_ERROR.
|
||||
|
@ -82,7 +106,7 @@ percpu_initlapic(void)
|
|||
// Send an Init Level De-Assert to synchronise arbitration ID's.
|
||||
lapicw(ICRHI, 0);
|
||||
lapicw(ICRLO, BCAST | INIT | LEVEL);
|
||||
while(lapic[ICRLO] & DELIVS)
|
||||
while(__am_lapic[ICRLO] & DELIVS)
|
||||
;
|
||||
|
||||
// Enable interrupts on the APIC (but not on the processor).
|
||||
|
@ -91,9 +115,9 @@ percpu_initlapic(void)
|
|||
|
||||
// Acknowledge interrupt.
|
||||
void
|
||||
lapic_eoi(void)
|
||||
__am_lapic_eoi(void)
|
||||
{
|
||||
if(lapic)
|
||||
if(__am_lapic)
|
||||
lapicw(EOI, 0);
|
||||
}
|
||||
|
||||
|
@ -110,7 +134,7 @@ microdelay(int us)
|
|||
// Start additional processor running entry code at addr.
|
||||
// See Appendix B of MultiProcessor Specification.
|
||||
void
|
||||
lapic_bootap(unsigned int apicid, unsigned int addr)
|
||||
__am_lapic_bootap(unsigned int apicid, unsigned int addr)
|
||||
{
|
||||
int i;
|
||||
unsigned short *wrv;
|
||||
|
@ -144,38 +168,6 @@ lapic_bootap(unsigned int apicid, unsigned int addr)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// The I/O APIC manages hardware interrupts for an SMP system.
|
||||
// http://www.intel.com/design/chipsets/datashts/29056601.pdf
|
||||
// See also picirq.c.
|
||||
|
||||
#include <am.h>
|
||||
#include <x86.h>
|
||||
|
||||
struct IOAPIC {
|
||||
uint32_t reg, pad[3], data;
|
||||
};
|
||||
typedef struct IOAPIC IOAPIC;
|
||||
|
||||
static volatile IOAPIC *ioapic;
|
||||
|
||||
#define IOAPIC_ADDR 0xFEC00000 // Default physical address of IO APIC
|
||||
|
||||
#define REG_ID 0x00 // Register index: ID
|
||||
#define REG_VER 0x01 // Register index: version
|
||||
#define REG_TABLE 0x10 // Redirection table base
|
||||
|
||||
// The redirection table starts at REG_TABLE and uses
|
||||
// two registers to configure each interrupt.
|
||||
// The first (low) register in a pair contains configuration bits.
|
||||
// The second (high) register contains a bitmask telling which
|
||||
// CPUs can serve that interrupt.
|
||||
#define INT_DISABLED 0x00010000 // Interrupt disabled
|
||||
#define INT_LEVEL 0x00008000 // Level-triggered (vs edge-)
|
||||
#define INT_ACTIVELOW 0x00002000 // Active low (vs high)
|
||||
#define INT_LOGICAL 0x00000800 // Destination is CPU id (vs APIC ID)
|
||||
|
||||
static unsigned int
|
||||
ioapicread(int reg)
|
||||
{
|
||||
|
@ -191,7 +183,7 @@ ioapicwrite(int reg, unsigned int data)
|
|||
}
|
||||
|
||||
void
|
||||
ioapic_init(void)
|
||||
__am_ioapic_init(void)
|
||||
{
|
||||
int i, maxintr;
|
||||
|
||||
|
@ -207,7 +199,7 @@ ioapic_init(void)
|
|||
}
|
||||
|
||||
void
|
||||
ioapic_enable(int irq, int cpunum)
|
||||
__am_ioapic_enable(int irq, int cpunum)
|
||||
{
|
||||
// Mark interrupt edge-triggered, active high,
|
||||
// enabled, and routed to the given cpunum,
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
#include "../../x86-qemu.h"
|
||||
|
||||
|
||||
void bootcpu_init() {
|
||||
void __am_bootcpu_init() {
|
||||
#define MAGIC 0x5f504d5f
|
||||
for (char *st = (char *)0xf0000; st != (char *)0xffffff; st ++) {
|
||||
if (*(volatile uint32_t *)st == MAGIC) {
|
||||
volatile MPConf *conf = ((volatile MPDesc *)st)->conf;
|
||||
lapic = conf->lapicaddr;
|
||||
__am_lapic = conf->lapicaddr;
|
||||
for (volatile char *ptr = (char *)(conf + 1);
|
||||
ptr < (char *)conf + conf->length; ptr += 8) {
|
||||
if (*ptr == '\0') {
|
||||
ptr += 12;
|
||||
if (++ncpu > MAX_CPU) {
|
||||
if (++__am_ncpu > MAX_CPU) {
|
||||
panic("cannot support > MAX_CPU processors");
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +21,7 @@ void bootcpu_init() {
|
|||
panic("seems not an x86-qemu virtual machine");
|
||||
}
|
||||
|
||||
void percpu_initgdt() {
|
||||
void __am_percpu_initgdt() {
|
||||
SegDesc *gdt = CPU->gdt;
|
||||
TSS *tss = &CPU->tss;
|
||||
gdt[SEG_KCODE] = SEG (STA_X | STA_R, 0, 0xffffffff, DPL_KERN);
|
||||
|
@ -34,22 +33,22 @@ void percpu_initgdt() {
|
|||
set_tr(KSEL(SEG_TSS));
|
||||
}
|
||||
|
||||
void thiscpu_setstk0(uintptr_t ss0, uintptr_t esp0) {
|
||||
void __am_thiscpu_setstk0(uintptr_t ss0, uintptr_t esp0) {
|
||||
CPU->tss.ss0 = ss0;
|
||||
CPU->tss.esp0 = esp0;
|
||||
}
|
||||
|
||||
void thiscpu_halt() {
|
||||
void __am_thiscpu_halt() {
|
||||
cli();
|
||||
while (1) hlt();
|
||||
}
|
||||
|
||||
void othercpu_halt() {
|
||||
bootrec->is_ap = 1;
|
||||
bootrec->entry = thiscpu_halt;
|
||||
for (int cpu = 0; cpu < ncpu; cpu++) {
|
||||
void __am_othercpu_halt() {
|
||||
__am_bootrec->is_ap = 1;
|
||||
__am_bootrec->entry = __am_thiscpu_halt;
|
||||
for (int cpu = 0; cpu < __am_ncpu; cpu++) {
|
||||
if (cpu != _cpu()) {
|
||||
lapic_bootap(cpu, 0x7c00);
|
||||
__am_lapic_bootap(cpu, 0x7c00);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ static int scan_code[] = {
|
|||
72, 80, 75, 77, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
size_t input_read(uintptr_t reg, void *buf, size_t size) {
|
||||
size_t __am_input_read(uintptr_t reg, void *buf, size_t size) {
|
||||
_DEV_INPUT_KBD_t *kbd = (_DEV_INPUT_KBD_t *)buf;
|
||||
|
||||
int status = inb(0x64);
|
||||
|
|
|
@ -17,7 +17,7 @@ static inline void port_write(int port, size_t nmemb, uintptr_t data) {
|
|||
}
|
||||
}
|
||||
|
||||
size_t pciconf_read(uintptr_t reg, void *buf, size_t size) {
|
||||
size_t __am_pciconf_read(uintptr_t reg, void *buf, size_t size) {
|
||||
outl(0xcf8, reg);
|
||||
switch (size) {
|
||||
case 1: *(uint8_t *) buf = inb(0xcfc + (reg & 3));
|
||||
|
@ -27,7 +27,7 @@ size_t pciconf_read(uintptr_t reg, void *buf, size_t size) {
|
|||
return size;
|
||||
}
|
||||
|
||||
size_t pciconf_write(uintptr_t reg, void *buf, size_t size) {
|
||||
size_t __am_pciconf_write(uintptr_t reg, void *buf, size_t size) {
|
||||
outl(0xcf8, reg);
|
||||
switch (size) {
|
||||
case 1: outb(0xcfc + (reg & 3), *(uint8_t *) buf);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
static _DEV_TIMER_DATE_t boot_date;
|
||||
static uint32_t freq_mhz = 2000;
|
||||
uint64_t uptsc;
|
||||
static uint64_t uptsc;
|
||||
|
||||
static inline uint64_t rdtsc() {
|
||||
uint32_t lo, hi;
|
||||
|
@ -58,13 +58,13 @@ static void get_date(_DEV_TIMER_DATE_t *rtc) {
|
|||
} while (tmp != rtc->second);
|
||||
}
|
||||
|
||||
void timer_init() {
|
||||
void __am_timer_init() {
|
||||
freq_mhz = estimate_freq();
|
||||
get_date(&boot_date);
|
||||
uptsc = rdtsc();
|
||||
}
|
||||
|
||||
size_t timer_read(uintptr_t reg, void *buf, size_t size) {
|
||||
size_t __am_timer_read(uintptr_t reg, void *buf, size_t size) {
|
||||
switch (reg) {
|
||||
case _DEVREG_TIMER_UPTIME: {
|
||||
uint64_t tsc = rdtsc() - uptsc;
|
||||
|
|
|
@ -52,14 +52,14 @@ static struct FBPixel {
|
|||
typedef struct FBPixel FBPixel;
|
||||
static int W, H;
|
||||
|
||||
void vga_init() {
|
||||
void __am_vga_init() {
|
||||
VBEInfo *info = (VBEInfo *)0x00004000;
|
||||
W = info->width;
|
||||
H = info->height;
|
||||
fb = (FBPixel*)(info->framebuffer);
|
||||
}
|
||||
|
||||
size_t video_read(uintptr_t reg, void *buf, size_t size) {
|
||||
size_t __am_video_read(uintptr_t reg, void *buf, size_t size) {
|
||||
switch(reg) {
|
||||
case _DEVREG_VIDEO_INFO: {
|
||||
_DEV_VIDEO_INFO_t *info = (_DEV_VIDEO_INFO_t *)buf;
|
||||
|
@ -71,7 +71,7 @@ size_t video_read(uintptr_t reg, void *buf, size_t size) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
size_t video_write(uintptr_t reg, void *buf, size_t size) {
|
||||
size_t __am_video_write(uintptr_t reg, void *buf, size_t size) {
|
||||
switch(reg) {
|
||||
case _DEVREG_VIDEO_FBCTL: {
|
||||
_DEV_VIDEO_FBCTL_t *ctl = (_DEV_VIDEO_FBCTL_t *)buf;
|
||||
|
|
|
@ -1,39 +1,39 @@
|
|||
#include "../x86-qemu.h"
|
||||
|
||||
void vga_init();
|
||||
void timer_init();
|
||||
void __am_vga_init();
|
||||
void __am_timer_init();
|
||||
|
||||
#define DEF_DEVOP(fn) \
|
||||
size_t fn(uintptr_t reg, void *buf, size_t size);
|
||||
|
||||
DEF_DEVOP(input_read);
|
||||
DEF_DEVOP(timer_read);
|
||||
DEF_DEVOP(video_read);
|
||||
DEF_DEVOP(video_write);
|
||||
DEF_DEVOP(pciconf_read);
|
||||
DEF_DEVOP(pciconf_write);
|
||||
DEF_DEVOP(__am_input_read);
|
||||
DEF_DEVOP(__am_timer_read);
|
||||
DEF_DEVOP(__am_video_read);
|
||||
DEF_DEVOP(__am_video_write);
|
||||
DEF_DEVOP(__am_pciconf_read);
|
||||
DEF_DEVOP(__am_pciconf_write);
|
||||
|
||||
size_t _io_read(uint32_t dev, uintptr_t reg, void *buf, size_t size) {
|
||||
switch (dev) {
|
||||
case _DEV_INPUT: return input_read(reg, buf, size);
|
||||
case _DEV_TIMER: return timer_read(reg, buf, size);
|
||||
case _DEV_VIDEO: return video_read(reg, buf, size);
|
||||
case _DEV_PCICONF: return pciconf_read(reg, buf, size);
|
||||
case _DEV_INPUT: return __am_input_read(reg, buf, size);
|
||||
case _DEV_TIMER: return __am_timer_read(reg, buf, size);
|
||||
case _DEV_VIDEO: return __am_video_read(reg, buf, size);
|
||||
case _DEV_PCICONF: return __am_pciconf_read(reg, buf, size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t _io_write(uint32_t dev, uintptr_t reg, void *buf, size_t size) {
|
||||
switch (dev) {
|
||||
case _DEV_VIDEO: return video_write(reg, buf, size);
|
||||
case _DEV_PCICONF: return pciconf_write(reg, buf, size);
|
||||
case _DEV_VIDEO: return __am_video_write(reg, buf, size);
|
||||
case _DEV_PCICONF: return __am_pciconf_write(reg, buf, size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _ioe_init() {
|
||||
if (_cpu() != 0) panic("init IOE in non-bootstrap CPU");
|
||||
timer_init();
|
||||
vga_init();
|
||||
__am_timer_init();
|
||||
__am_vga_init();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#include "../x86-qemu.h"
|
||||
|
||||
int ncpu = 0;
|
||||
struct cpu_local cpuinfo[MAX_CPU];
|
||||
int __am_ncpu = 0;
|
||||
struct cpu_local __am_cpuinfo[MAX_CPU];
|
||||
volatile struct boot_info *__am_bootrec = (void *)0x7000;
|
||||
|
||||
static void (* volatile user_entry)();
|
||||
static volatile intptr_t apboot_done = 0;
|
||||
volatile struct boot_info *bootrec = (void *)0x7000;
|
||||
|
||||
static void percpu_entry();
|
||||
static void ap_entry();
|
||||
|
@ -18,11 +19,11 @@ int _mpe_init(void (*entry)()) {
|
|||
}
|
||||
|
||||
int _ncpu() {
|
||||
return ncpu;
|
||||
return __am_ncpu;
|
||||
}
|
||||
|
||||
int _cpu(void) {
|
||||
return lapic[8] >> 24;
|
||||
return __am_lapic[8] >> 24;
|
||||
}
|
||||
|
||||
intptr_t _atomic_xchg(volatile intptr_t *addr, intptr_t newval) {
|
||||
|
@ -34,10 +35,10 @@ intptr_t _atomic_xchg(volatile intptr_t *addr, intptr_t newval) {
|
|||
|
||||
static void percpu_entry() {
|
||||
if (_cpu() == 0) { // bootstrap cpu, boot all aps
|
||||
for (int cpu = 1; cpu < ncpu; cpu++) {
|
||||
bootrec->is_ap = 1;
|
||||
bootrec->entry = percpu_entry;
|
||||
lapic_bootap(cpu, 0x7c00);
|
||||
for (int cpu = 1; cpu < __am_ncpu; cpu++) {
|
||||
__am_bootrec->is_ap = 1;
|
||||
__am_bootrec->entry = percpu_entry;
|
||||
__am_lapic_bootap(cpu, 0x7c00);
|
||||
while (_atomic_xchg(&apboot_done, 0) != 1) {
|
||||
pause();
|
||||
}
|
||||
|
@ -49,10 +50,10 @@ static void percpu_entry() {
|
|||
}
|
||||
|
||||
static void ap_entry() {
|
||||
percpu_initgdt();
|
||||
percpu_initirq();
|
||||
percpu_initlapic();
|
||||
percpu_initpg();
|
||||
__am_percpu_initgdt();
|
||||
__am_percpu_initirq();
|
||||
__am_percpu_initlapic();
|
||||
__am_percpu_initpg();
|
||||
_atomic_xchg(&apboot_done, 1);
|
||||
user_entry();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "../x86-qemu.h"
|
||||
|
||||
volatile uint32_t trace_flags = 0; // current trace status
|
||||
static volatile uint32_t trace_flags = 0; // current trace status
|
||||
LOCKDEF(trace);
|
||||
|
||||
void _trace_on(uint32_t flags) {
|
||||
|
|
|
@ -6,11 +6,11 @@ int main();
|
|||
static void heap_init();
|
||||
|
||||
void _start() { // the bootloader jumps here
|
||||
bootcpu_init();
|
||||
__am_bootcpu_init();
|
||||
heap_init();
|
||||
percpu_initgdt();
|
||||
percpu_initlapic();
|
||||
ioapic_init();
|
||||
__am_percpu_initgdt();
|
||||
__am_percpu_initlapic();
|
||||
__am_ioapic_init();
|
||||
_halt(main());
|
||||
}
|
||||
|
||||
|
@ -21,12 +21,12 @@ void _putc(char ch) { // only works for x86-qemu
|
|||
|
||||
void _halt(int code) {
|
||||
cli();
|
||||
othercpu_halt();
|
||||
__am_othercpu_halt();
|
||||
char buf[] = "Exited (#).\n";
|
||||
for (char *p = buf; *p; p++) {
|
||||
_putc((*p == '#') ? ('0' + code) : *p);
|
||||
}
|
||||
thiscpu_halt();
|
||||
__am_thiscpu_halt();
|
||||
}
|
||||
|
||||
static void heap_init() {
|
||||
|
|
|
@ -26,7 +26,7 @@ int vme_init(void *(*pgalloc_f)(size_t), void (*pgfree_f)(void *)) {
|
|||
pgfree_usr = pgfree_f;
|
||||
|
||||
kpt = pgalloc();
|
||||
for (int i = 0; i < NELEM(areas); i++) {
|
||||
for (int i = 0; i < LENGTH(areas); i++) {
|
||||
const struct vm_area *seg = &areas[i];
|
||||
if (!seg->physical) continue;
|
||||
for (uint32_t pa = (uint32_t)seg->area.start;
|
||||
|
@ -42,11 +42,11 @@ int vme_init(void *(*pgalloc_f)(size_t), void (*pgfree_f)(void *)) {
|
|||
ptab[PTX(pa)] = PTE_P | PTE_W | pa;
|
||||
}
|
||||
}
|
||||
percpu_initpg(); // set CR3 and CR0 if kpt is not NULL
|
||||
__am_percpu_initpg(); // set CR3 and CR0 if kpt is not NULL
|
||||
return 0;
|
||||
}
|
||||
|
||||
void percpu_initpg() { // called by all cpus
|
||||
void __am_percpu_initpg() { // called by all cpus
|
||||
if (kpt) {
|
||||
set_cr3(kpt);
|
||||
set_cr0(get_cr0() | CR0_PG);
|
||||
|
|
|
@ -19,29 +19,29 @@ struct cpu_local {
|
|||
TSS tss;
|
||||
uint8_t stack[4096];
|
||||
};
|
||||
extern volatile uint32_t *lapic;
|
||||
extern volatile struct boot_info *bootrec;
|
||||
extern int ncpu;
|
||||
extern struct cpu_local cpuinfo[MAX_CPU];
|
||||
#define CPU (&cpuinfo[_cpu()])
|
||||
extern volatile uint32_t *__am_lapic;
|
||||
extern volatile struct boot_info *__am_bootrec;
|
||||
extern int __am_ncpu;
|
||||
extern struct cpu_local __am_cpuinfo[MAX_CPU];
|
||||
#define CPU (&__am_cpuinfo[_cpu()])
|
||||
|
||||
#define NELEM(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
#define LENGTH(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
|
||||
// apic utils
|
||||
void lapic_eoi();
|
||||
void ioapic_init();
|
||||
void lapic_bootap(unsigned int cpu, uint32_t address);
|
||||
void ioapic_enable(int irq, int cpu);
|
||||
void __am_lapic_eoi();
|
||||
void __am_ioapic_init();
|
||||
void __am_lapic_bootap(unsigned int cpu, uint32_t address);
|
||||
void __am_ioapic_enable(int irq, int cpu);
|
||||
|
||||
// per-cpu x86-specific operations
|
||||
void bootcpu_init();
|
||||
void percpu_initirq();
|
||||
void percpu_initgdt();
|
||||
void percpu_initlapic();
|
||||
void percpu_initpg();
|
||||
void thiscpu_setstk0(uintptr_t ss0, uintptr_t esp0);
|
||||
void thiscpu_halt() __attribute__((__noreturn__));
|
||||
void othercpu_halt();
|
||||
void __am_bootcpu_init();
|
||||
void __am_percpu_initirq();
|
||||
void __am_percpu_initgdt();
|
||||
void __am_percpu_initlapic();
|
||||
void __am_percpu_initpg();
|
||||
void __am_thiscpu_setstk0(uintptr_t ss0, uintptr_t esp0);
|
||||
void __am_thiscpu_halt() __attribute__((__noreturn__));
|
||||
void __am_othercpu_halt();
|
||||
|
||||
// simple spin locks
|
||||
#define LOCKDECL(name) \
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define COMMON_H
|
||||
|
||||
#include <am.h>
|
||||
#include <amdev.h>
|
||||
#include <klib.h>
|
||||
|
||||
typedef uint8_t byte;
|
||||
|
|
Loading…
Reference in New Issue