redesign am api

This commit is contained in:
Yanyan Jiang 2017-08-23 08:57:38 -04:00
parent 91aedb3d0b
commit b9b97feb99
9 changed files with 113 additions and 86 deletions

10
SPEC.md
View File

@ -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环境变量envpargv和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);`原子交换两数。保证内存顺序一致性。

91
am/am.h
View File

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

View File

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

View File

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

View File

@ -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<uint32_t*>(0x7000) = 0x007c00ea; // code for ljmp
*reinterpret_cast<uint32_t*>(0x7004) = 0x00000000;
@ -111,7 +115,8 @@ intptr_t _atomic_xchg(volatile intptr_t *addr, intptr_t newval) {
return result;
}
/*
void _barrier() {
asm volatile("":::"memory");
}
*/

View File

@ -1,4 +1,4 @@
NAME = ioetest
SRCS = main.c
SRCS = main.cpp
LIBS += klib
include $(AM_HOME)/Makefile.app

View File

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

4
tests/mptest/Makefile Normal file
View File

@ -0,0 +1,4 @@
NAME = mptest
SRCS = main.cpp
LIBS += klib
include $(AM_HOME)/Makefile.app

15
tests/mptest/main.cpp Normal file
View File

@ -0,0 +1,15 @@
#include <am.h>
#include <amdev.h>
#include <klib.h>
void f() {
printf("%d / %d\n", _cpu(), _ncpu());
while (1);
}
int main() {
_asye_init(nullptr);
_mpe_init(f);
assert(0);
return 0;
}