redesign am api
This commit is contained in:
parent
91aedb3d0b
commit
b9b97feb99
10
SPEC.md
10
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);`原子交换两数。保证内存顺序一致性。
|
||||
|
|
91
am/am.h
91
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
|
||||
}
|
||||
|
|
30
am/amdev.h
30
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
NAME = ioetest
|
||||
SRCS = main.c
|
||||
SRCS = main.cpp
|
||||
LIBS += klib
|
||||
include $(AM_HOME)/Makefile.app
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
NAME = mptest
|
||||
SRCS = main.cpp
|
||||
LIBS += klib
|
||||
include $(AM_HOME)/Makefile.app
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue