From b9b97feb99f574c49c149ab0328874169e290ee2 Mon Sep 17 00:00:00 2001 From: Yanyan Jiang Date: Wed, 23 Aug 2017 08:57:38 -0400 Subject: [PATCH] redesign am api --- SPEC.md | 10 ++-- am/am.h | 91 +++++++++++++++++------------------ am/amdev.h | 30 +++++++++--- am/arch/x86-qemu/src/asye.cpp | 8 +-- am/arch/x86-qemu/src/mpe.cpp | 13 +++-- tests/ioetest/Makefile | 2 +- tests/ioetest/main.cpp | 26 +++++----- tests/mptest/Makefile | 4 ++ tests/mptest/main.cpp | 15 ++++++ 9 files changed, 113 insertions(+), 86 deletions(-) create mode 100644 tests/mptest/Makefile create mode 100644 tests/mptest/main.cpp diff --git a/SPEC.md b/SPEC.md index 175bbaae..861220b7 100644 --- a/SPEC.md +++ b/SPEC.md @@ -86,17 +86,13 @@ * `void _map(_Protect *p, void *va, void *pa, uint8_t mode);`将地址空间的虚拟地址va映射到物理地址pa。单位为一页。 * `void _unmap(_Protect *p, void *va);`释放虚拟地址空间va的一页。 * `void _switch(_Protect *p);`切换到一个保护的地址空间。注意在内核态下,内核代码将始终可用。 -* `_RegSet *_umake(_Protect *p, _Area ustack, _Area kstack, void *entry, char *const argv[], char *const envp[]);`创建一个用户进程(地址空间p,用户栈地址ustack,内核栈地址kstack,入口地址entry,参数argv,环境变量envp,argv和envp均以NULL结束). +* `_RegSet *_umake(_Protect *p, _Area ustack, _Area kstack, void *entry, void *arg);`创建一个用户进程(地址空间p,用户栈地址ustack,内核栈地址kstack,入口地址entry,参数arg). ## Multi-Processor Extension (多处理器扩展) -### 数据结构与静态数据 - -* `extern int _NR_CPU;`处理器数量。 - ### MPE API * `void _mpe_init(void (*entry)());`启动多处理器。 +* `int _ncpu();`返回number of CPU。 * `int _cpu();`返回当前CPU的编号(从0开始)。 -* `intptr_t _atomic_xchg(volatile void *addr, intptr_t newval);`原子交换两数。 -* `void _barrier();`保证内存顺序一致性。 +* `intptr_t _atomic_xchg(volatile void *addr, intptr_t newval);`原子交换两数。保证内存顺序一致性。 diff --git a/am/am.h b/am/am.h index 5570ed67..995fcd63 100755 --- a/am/am.h +++ b/am/am.h @@ -1,9 +1,8 @@ /* - * The Nexus Abstract Architecture - * Minmal architectural-independent library for implementing system software - * - * Please refer to the AM specification + * The Nexus Abstract Machine Architecture (AM) + * A minimal architectural-independent library for implementing system software */ + #ifndef __AM_H__ #define __AM_H__ @@ -19,22 +18,6 @@ typedef struct _Area { void *start, *end; } _Area; -#ifdef __cplusplus -extern "C" { -#endif - -// ======================================================================= -// [0] Turing Machine: code execution & a heap memory -// ======================================================================= - -void _putc(char ch); -void _halt(int code); -extern _Area _heap; - -// ======================================================================= -// [1] IO Extension (IOE) -// ======================================================================= - typedef struct _Device { uint32_t id; const char *name; @@ -42,6 +25,43 @@ typedef struct _Device { void (*write)(uintptr_t reg, size_t nmemb, uintptr_t data); } _Device; +typedef struct _RegSet _RegSet; + +enum { + _EVENT_NULL = 0, + _EVENT_IRQ_TIMER, _EVENT_IRQ_IODEV, + _EVENT_ERROR, + _EVENT_NUMERIC, + _EVENT_PAGE_FAULT, + _EVENT_TRAP, _EVENT_SYSCALL, +}; + +typedef struct _Event { + int event; + uintptr_t cause, ref; +} _Event; + +typedef struct _Protect { + _Area area; + void *ptr; +} _Protect; + +#ifdef __cplusplus +extern "C" { +#endif + +// ======================================================================= +// [0] Turing Machine +// ======================================================================= + +extern _Area _heap; +void _putc(char ch); +void _halt(int code); + +// ======================================================================= +// [1] I/O Extension (IOE) +// ======================================================================= + void _ioe_init(); _Device *_device(int n); @@ -49,26 +69,7 @@ _Device *_device(int n); // [2] Asynchronous Extension (ASYE) // ======================================================================= -#define _EVENTS(_) \ - _(IRQ_TIME) _(IRQ_IODEV) \ - _(ERROR) _(PAGE_FAULT) _(BUS_ERROR) _(NUMERIC) \ - _(TRAP) _(SYSCALL) - -#define _EVENT_NAME(ev) _EVENT_##ev, - -enum { - _EVENT_NULL = 0, - _EVENTS(_EVENT_NAME) -}; - -typedef struct _RegSet _RegSet; - -typedef struct _Event { - int event; - intptr_t cause; -} _Event; - -void _asye_init(_RegSet* (*l)(_Event ev, _RegSet *regs)); +void _asye_init(_RegSet *(*l)(_Event ev, _RegSet *regs)); _RegSet *_make(_Area kstack, void *entry, void *arg); void _trap(); int _istatus(int enable); @@ -77,28 +78,22 @@ int _istatus(int enable); // [3] Protection Extension (PTE) // ======================================================================= -typedef struct _Protect { - _Area area; - void *ptr; -} _Protect; - void _pte_init(void*(*palloc)(), void (*pfree)(void*)); void _protect(_Protect *p); void _release(_Protect *p); void _map(_Protect *p, void *va, void *pa, uint8_t mode); void _unmap(_Protect *p, void *va); void _switch(_Protect *p); -_RegSet *_umake(_Protect *p, _Area ustack, _Area kstack, void *entry, char *const argv[], char *const envp[]); +_RegSet *_umake(_Protect *p, _Area ustack, _Area kstack, void *entry, void *arg); // ======================================================================= // [4] Multi-Processor Extension (MPE) // ======================================================================= void _mpe_init(void (*entry)()); +int _ncpu(); int _cpu(); intptr_t _atomic_xchg(volatile intptr_t *addr, intptr_t newval); -void _barrier(); -extern int _NR_CPU; #ifdef __cplusplus } diff --git a/am/amdev.h b/am/amdev.h index 30e6ec1f..630fa075 100644 --- a/am/amdev.h +++ b/am/amdev.h @@ -1,5 +1,5 @@ -#ifndef __DEV_H__ -#define __DEV_H__ +#ifndef __AMDEV_H__ +#define __AMDEV_H__ #define _DEV_PERFCNT 0x0000ac01 #define _DEV_INPUT 0x0000ac02 @@ -9,10 +9,9 @@ #define _DEV_ATA0 0x00000dd0 #define _DEV_ATA1 0x00000dd1 +// Performance Counter (0000ac01) -// performance counter (0000ac01) - -// console (0000ac02) +// Input (0000ac02) #define _DEV_INPUT_REG_KBD 1 @@ -32,11 +31,11 @@ enum { _KEYS(_KEY_NAME) }; -// timer (0000ac01) +// Timer (0000ac03) #define _DEV_TIMER_REG_UPTIME 1 -// video (0000ac01) +// Video (0000ac04) #define _DEV_VIDEO_REG_WIDTH 1 #define _DEV_VIDEO_REG_HEIGHT 2 @@ -48,4 +47,21 @@ enum { #define _DEV_VIDEO_REG_DRAW 8 #define _DEV_VIDEO_REG_SYNC 9 +// PCI Configuration (00000080) + +static inline uint32_t _DEV_PCICONF_REG(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) { + return ((uint32_t)1 << 31) | ((uint32_t)bus << 16) | ((uint32_t)slot << 11) | ((uint32_t)func << 8) | offset; +} + +// ATA (00000dd0 -- 00000dd1) + +#define _DEV_ATA_REG_DATA 0 +#define _DEV_ATA_REG_FEATURE 1 +#define _DEV_ATA_REG_NSECT 2 +#define _DEV_ATA_REG_SECT 3 +#define _DEV_ATA_REG_CYLOW 4 +#define _DEV_ATA_REG_CYHIGH 5 +#define _DEV_ATA_REG_DRIVE 6 +#define _DEV_ATA_REG_STATUS 7 + #endif diff --git a/am/arch/x86-qemu/src/asye.cpp b/am/arch/x86-qemu/src/asye.cpp index c19c8d08..19110a43 100644 --- a/am/arch/x86-qemu/src/asye.cpp +++ b/am/arch/x86-qemu/src/asye.cpp @@ -64,7 +64,7 @@ void irq_handle(TrapFrame *tf) { args[3] = regs.ebx; ev.event = _EVENT_NULL; - if (tf->irq == 32) ev.event = _EVENT_IRQ_TIME; + if (tf->irq == 32) ev.event = _EVENT_IRQ_TIMER; else if (tf->irq == 33) ev.event = _EVENT_IRQ_IODEV; else if (tf->irq == 0x80) { ev.event = _EVENT_TRAP; @@ -168,10 +168,9 @@ void irq_handle(TrapFrame *tf) { } -static GateDesc idt[NR_IRQ]; - void _asye_init(_RegSet*(*h)(_Event, _RegSet*)) { + static GateDesc idt[NR_IRQ]; smp_init(); lapic_init(); ioapic_enable(IRQ_KBD, 0); @@ -208,13 +207,14 @@ void _asye_init(_RegSet*(*h)(_Event, _RegSet*)) { } _RegSet *_make(_Area stack, void *entry, void *arg) { - // TODO: pass arg _RegSet *regs = (_RegSet*)stack.start; regs->esp0 = reinterpret_cast(stack.end); regs->cs = KSEL(SEG_KCODE); regs->ds = regs->es = regs->ss = KSEL(SEG_KDATA); regs->eip = (uint32_t)entry; regs->eflags = FL_IF; + regs->esp0 -= 4; + *((void**)(regs->esp0)) = arg; return regs; } diff --git a/am/arch/x86-qemu/src/mpe.cpp b/am/arch/x86-qemu/src/mpe.cpp index 07db43f4..050c2fee 100644 --- a/am/arch/x86-qemu/src/mpe.cpp +++ b/am/arch/x86-qemu/src/mpe.cpp @@ -38,7 +38,7 @@ struct MPDesc { }; typedef struct MPDesc MPDesc; -int _NR_CPU = 0; +int numcpu = 0; extern uint32_t *lapic; static MPDesc *search() { @@ -66,7 +66,7 @@ void smp_init() { switch (*p) { case MP_PROC: { p += 20; // CPU desc has 20 bytes - _NR_CPU ++; + numcpu ++; break; } default: @@ -75,6 +75,10 @@ void smp_init() { } } +int _ncpu() { + return numcpu; +} + static void (* volatile _entry)(); static intptr_t ap_boot = 0; @@ -91,7 +95,7 @@ static void mp_entry() { void _mpe_init(void (*entry)()) { _entry = entry; - for (int cpu = 1; cpu < _NR_CPU; cpu ++) { + for (int cpu = 1; cpu < numcpu; cpu ++) { *(uint16_t*)(0x7c00 + 510) = 0x55aa; *reinterpret_cast(0x7000) = 0x007c00ea; // code for ljmp *reinterpret_cast(0x7004) = 0x00000000; @@ -111,7 +115,8 @@ intptr_t _atomic_xchg(volatile intptr_t *addr, intptr_t newval) { return result; } +/* void _barrier() { asm volatile("":::"memory"); } - +*/ diff --git a/tests/ioetest/Makefile b/tests/ioetest/Makefile index d86004b7..6cba0072 100644 --- a/tests/ioetest/Makefile +++ b/tests/ioetest/Makefile @@ -1,4 +1,4 @@ NAME = ioetest -SRCS = main.c +SRCS = main.cpp LIBS += klib include $(AM_HOME)/Makefile.app diff --git a/tests/ioetest/main.cpp b/tests/ioetest/main.cpp index 8b8775c9..7a032c9c 100644 --- a/tests/ioetest/main.cpp +++ b/tests/ioetest/main.cpp @@ -4,12 +4,8 @@ _Device *pci; -uint32_t addr(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) { - return (1 << 31) | (bus << 16) | (slot << 11) | (func << 8) | offset; -} - uint32_t pci_conf_read(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) { - return pci->read(addr(bus, slot, func, offset), 4); + return pci->read(_DEV_PCICONF_REG(bus, slot, func, offset), 4); } struct pcidev { @@ -39,24 +35,24 @@ void pci_test(_Device *dev) { void timer_test(_Device *dev) { uint32_t t0 = dev->read(_DEV_TIMER_REG_UPTIME, 4); - for (int volatile i = 0; i < 10000000; i ++) ; + for (int volatile i = 0; i < 1000000; i ++) ; uint32_t t1 = dev->read(_DEV_TIMER_REG_UPTIME, 4); - printk("Loop 10^7 time elapse: %d ms\n", t1 - t0); + printk("Loop 10^6 time elapse: %d ms\n", t1 - t0); } void ata_test(_Device *dev) { - while ((dev->read(7, 1) & 0xc0) != 0x40); + while ((dev->read(_DEV_ATA_REG_STATUS, 1) & 0xc0) != 0x40); int offset = 0; - dev->write(2, 1, 1); - dev->write(3, 1, offset); - dev->write(4, 1, offset >> 8); - dev->write(5, 1, offset >> 16); - dev->write(6, 1, (offset >> 24) | 0xe0); - dev->write(7, 1, 0x20); + dev->write(_DEV_ATA_REG_NSECT, 1, 1); + dev->write(_DEV_ATA_REG_SECT, 1, offset); + dev->write(_DEV_ATA_REG_CYLOW, 1, offset >> 8); + dev->write(_DEV_ATA_REG_CYHIGH, 1, offset >> 16); + dev->write(_DEV_ATA_REG_DRIVE, 1, (offset >> 24) | 0xe0); + dev->write(_DEV_ATA_REG_STATUS, 1, 0x20); while ((dev->read(7, 1) & 0xc0) != 0x40); uint32_t buf[512 / 4]; for (int i = 0; i < 512 / 4; i ++) { - buf[i] = dev->read(0, 4); + buf[i] = dev->read(_DEV_ATA_REG_DATA, 4); } for (int i = 0; i < 512; i ++) { printf("%02x ", ((char*)buf)[i] & 0xff); diff --git a/tests/mptest/Makefile b/tests/mptest/Makefile new file mode 100644 index 00000000..0024f091 --- /dev/null +++ b/tests/mptest/Makefile @@ -0,0 +1,4 @@ +NAME = mptest +SRCS = main.cpp +LIBS += klib +include $(AM_HOME)/Makefile.app diff --git a/tests/mptest/main.cpp b/tests/mptest/main.cpp new file mode 100644 index 00000000..ebee0993 --- /dev/null +++ b/tests/mptest/main.cpp @@ -0,0 +1,15 @@ +#include +#include +#include + +void f() { + printf("%d / %d\n", _cpu(), _ncpu()); + while (1); +} + +int main() { + _asye_init(nullptr); + _mpe_init(f); + assert(0); + return 0; +}