x86-qemu, makefiles: simplify ld commands

This commit is contained in:
Yanyan Jiang 2019-05-06 17:11:43 +08:00
parent 38a7ad8ed9
commit 6102652dc8
20 changed files with 135 additions and 139 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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() {

View File

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

View File

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

View File

@ -2,6 +2,7 @@
#define COMMON_H
#include <am.h>
#include <amdev.h>
#include <klib.h>
typedef uint8_t byte;