/* CONDEV: which device to use for the kernel console (DEV_VID or DEV_SER) */
#define CONDEV DEV_VID
+/* maximum number of open files per process */
+#define PROC_MAXFD 16
+/* maximum number of processes */
+#define MAX_PROCS 24
+
#endif /* CONFIG_H_ */
#ifndef DBG_H_
#define DBG_H_
-__attribute__((noreturn))
-void panic(const char *fmt, ...);
+void panic(const char *fmt, ...) __attribute__((noreturn));
void dbgping(int c);
#include "fs.h"
-enum { FILE_REG, FILE_CDEV, FILE_BDEV };
+enum { FILE_INVAL, FILE_REG, FILE_CDEV, FILE_BDEV };
struct device;
%endmacro
intr_entry_common:
+ push es
+ push ds
push ax
mov ax, sp
- add ax, 2
+ add ax, 14 ; sp before the interrupt (3 here + 1 above + 3 cpu) * 2
push cx
push dx
push bx
- push ax ; saved sp
+ push ax ; calculated original sp
push bp
push si
push di
pop dx
pop cx
pop ax
+ pop ds
+ pop es
add sp, 2 ; remove interrupt number from the stack
iret
mov ax, [bp + 4]
mov [cs:.intop + 1], al ; modify int instruction
- mov [saved_sp], sp
+ mov [cs:saved_sp], sp
mov sp, [bp + 6]
pop ax
pop bx
pop si
pop di
popf
- mov sp, [saved_sp]
+ mov sp, [cs:saved_sp]
.intop: int 0xff
- mov [saved_ax], ax
+ mov [cs:saved_ax], ax
pushf
pop ax
mov sp, [bp + 8]
add sp, 14 ; sp at end of outregs
push ax ; flags
- mov ax, [saved_ax]
+ mov ax, [cs:saved_ax]
push di
push si
push dx
push bx
push ax
- mov sp, [saved_sp]
+ mov sp, [cs:saved_sp]
popf
pop di
pop si
saved_sp dw 0
saved_ax dw 0
+ ; takes a far pointer to the target stack which should contain an
+ ; intr_frame, switches to that stack, restores the CPU state and
+ ; executes an iret
+ global intr_ret
+intr_ret:
+ add ax, 2 ; discard return address
+ pop ss ; new stack segment
+ pop sp ; stack pointer to the intr_frame in the new stack
+ ; restore general purpose registers
+ pop di
+ pop si
+ pop bp
+ pop bx ; ignore sp
+ pop bx
+ pop dx
+ pop cx
+ pop ax
+ pop ds
+ pop es
+ add sp, 2 ; skip intr num
+ iret
+
; vi:ts=8 sts=8 sw=8 ft=nasm:
#include "intr.h"
+#include "sys.h"
/* PIC command and data ports */
#define PIC1_CMD 0x20
}
set_intr_vect(0, 0, (uint16_t)intr_entry_div);
+ set_intr_vect(0x80, 0, (uint16_t)sys_enter);
}
void dispatch_intr(struct intr_frame frm)
struct intr_frame {
/* registers pushed by intr_entry_* */
struct registers regs;
+ /* data segment registers */
+ uint16_t ds, es;
/* interrupt number */
uint16_t inum;
/* pushed by CPU during interrupt entry */
#include "ser.h"
#include "con.h"
#include "mem.h"
+#include "proc.h"
#include "dbg.h"
void kmain(void)
{
- int i;
-
vid_init();
ser_init();
con_init();
- mem_init();
printf("eightysix kernel %s\n", VERSTR);
- printf("initial kmalloc stats\n");
- dbg_print_kmalloc_stats();
- printf("initial free pool\n");
- dbg_print_kmalloc_pool();
-
- void __far *ptr[32];
-
- for(i=0; i<32; i++) {
- ptr[i] = kmalloc(256);
- printf("ALLOC(256) - %x:%x\n", FP_SEG(ptr[i]), FP_OFFS(ptr[i]));
- }
-
- printf("\nallocated 32 256b blocks ... ");
- dbg_print_kmalloc_stats();
- dbg_print_kmalloc_pool();
-
- for(i=0; i<32; i++) {
- int idx = rand() & 0x1f;
- while(!ptr[idx]) {
- idx = (idx + 1) & 0x1f;
- }
- if(ptr[idx]) {
- printf("FREE(%x:%x)\n", FP_SEG(ptr[idx]), FP_OFFS(ptr[idx]));
- kfree(ptr[idx]);
- ptr[idx] = 0;
- dbg_print_kmalloc_pool();
- }
- }
-
- printf("\nafter freeing some... kmalloc free pool\n");
- dbg_print_kmalloc_stats();
- dbg_print_kmalloc_pool();
-
+ mem_init();
init_intr();
+
+ printf("starting init\n");
+ proc_init();
}
--- /dev/null
+#include <string.h>
+#include "proc.h"
+#include "mem.h"
+#include "intr.h"
+#include "asmutil.h"
+#include "dbg.h"
+
+int curpid;
+struct process procs[MAX_PROCS];
+
+static int curtime;
+static struct process *runlist, *runtail, *blklist, *blktail;
+static int num_run, num_blk;
+
+void intr_ret(void __far *sp);
+
+void proc_init(void)
+{
+ struct process *p;
+ struct intr_frame __far *sp;
+ int start;
+
+ p = procs + 1;
+ /* allocate space for the test init */
+ if((start = alloc_blocks(16)) == -1) {
+ panic("failed to allocate memory for the test init process");
+ }
+ p->state = PROC_RUN;
+ p->tseg = p->dseg = start << 6;
+ p->sp = 65536 - sizeof(struct intr_frame);
+ runlist = runtail = p;
+
+ sp = MK_FP(p->dseg, p->sp);
+ fmemset(&sp->regs, 0, sizeof sp->regs);
+ sp->regs.sp = FP_OFFS(sp);
+ sp->inum = 0;
+ sp->ip = 0;
+ sp->cs = p->tseg;
+ sp->flags = 0;
+
+ intr_ret(sp);
+}
--- /dev/null
+#ifndef PROC_H_
+#define PROC_H_
+
+#include "config.h"
+#include <inttypes.h>
+#include "file.h"
+
+enum {
+ PROC_INVAL,
+ PROC_RUN,
+ PROC_BLK
+};
+
+struct process {
+ int state;
+ int uid, gid, euid, egid;
+ uint16_t tseg, dseg;
+ uint16_t sp;
+ unsigned long brk;
+ void __far *waitaddr;
+
+ struct file files[PROC_MAXFD];
+
+ struct process *next;
+};
+
+extern int curpid;
+extern struct process procs[MAX_PROCS];
+
+void proc_init(void);
+
+void schedule(void);
+
+int sys_fork(void);
+int sys_vfork(void);
+
+#endif /* PROC_H_ */
--- /dev/null
+; early processes test, hardcoded init
+ cpu 8086
+ bits 16
+ section .text
+
+ global ptest
+ptest:
+ mov ax, 64 ; sys_dbgwrite
+ mov bx, str_hello
+ mov cx, 7 ; size
+ int 80h
+
+.inf: jmp .inf
+
+ section .rodata
+str_hello db 'hello!',10
--- /dev/null
+#include <stdio.h>
+#include "sys.h"
+#include "proc.h"
+
+void sys_dbgwrite(struct registers *regs);
+
+void sys_enter(struct intr_frame *frm)
+{
+ switch(frm->regs.ax) {
+ case SYS_EXIT:
+ case SYS_OPEN:
+ case SYS_CLOSE:
+ case SYS_READ:
+ case SYS_WRITE:
+ case SYS_GETPID:
+ case SYS_FORK:
+ case SYS_VFORK:
+ case SYS_EXEC:
+ break;
+
+ case SYS_DBGWRITE:
+ sys_dbgwrite(&frm->regs);
+ break;
+
+ default:
+ printf("invalid system call: %x\n", frm->regs.ax);
+ }
+}
+
+void sys_dbgwrite(struct registers *regs)
+{
+ unsigned int i;
+ char __far *str = MK_FP(procs[curpid].dseg, regs->bx);
+ for(i=0; i<regs->cx; i++) {
+ putchar(str[i]);
+ }
+}
--- /dev/null
+#ifndef SYS_H_
+#define SYS_H_
+
+#include "intr.h"
+
+enum {
+ SYS_EXIT = 0,
+ SYS_OPEN = 1,
+ SYS_CLOSE = 2,
+ SYS_READ = 3,
+ SYS_WRITE = 4,
+ SYS_GETPID = 5,
+ SYS_FORK = 6,
+ SYS_VFORK = 7,
+ SYS_EXEC = 8,
+ SYS_DBGWRITE = 64
+};
+
+void sys_enter(struct intr_frame *frm);
+
+#endif /* SYS_H_ */