提交 5628c3d8 创建 作者: Silas Boyd-Wickizer's avatar Silas Boyd-Wickizer

CP -- proc.c and trapasm.S hacking..

上级 54ee87d7
...@@ -8,6 +8,13 @@ namecmp(const char *s, const char *t) ...@@ -8,6 +8,13 @@ namecmp(const char *s, const char *t)
return strncmp(s, t, DIRSIZ); return strncmp(s, t, DIRSIZ);
} }
struct inode*
namei(char *path)
{
panic("namei");
return NULL;
}
#if 0 #if 0
// File system implementation. Four layers: // File system implementation. Four layers:
// + Blocks: allocator for raw disk blocks. // + Blocks: allocator for raw disk blocks.
......
...@@ -12,6 +12,8 @@ static inline void *p2v(uptr a) { return (void *) a + KBASE; } ...@@ -12,6 +12,8 @@ static inline void *p2v(uptr a) { return (void *) a + KBASE; }
struct spinlock; struct spinlock;
struct condvar; struct condvar;
struct proc; struct proc;
struct vmnode;
struct vmap;
// bio.c // bio.c
void binit(void); void binit(void);
...@@ -34,6 +36,7 @@ void snprintf(char *buf, u32 n, char *fmt, ...); ...@@ -34,6 +36,7 @@ void snprintf(char *buf, u32 n, char *fmt, ...);
// fs.c // fs.c
int namecmp(const char*, const char*); int namecmp(const char*, const char*);
struct inode* namei(char*);
// ide.c // ide.c
void ideinit(void); void ideinit(void);
...@@ -145,3 +148,9 @@ int strcmp(const char *p, const char *q); ...@@ -145,3 +148,9 @@ int strcmp(const char *p, const char *q);
// uart.c // uart.c
void uartputc(char c); void uartputc(char c);
// vm.c
struct vmap * vmap_alloc(void);
struct vmnode* vmn_allocpg(u64 npg);
int vmap_insert(struct vmap *, struct vmnode *n, uptr);
int copyout(struct vmap *, uptr, void*, u64);
...@@ -14,6 +14,7 @@ extern void initkalloc(void); ...@@ -14,6 +14,7 @@ extern void initkalloc(void);
extern void initrcu(void); extern void initrcu(void);
extern void initproc(void); extern void initproc(void);
extern void initbio(void); extern void initbio(void);
extern void inituser(void);
void void
cmain(void) cmain(void)
...@@ -38,6 +39,8 @@ cmain(void) ...@@ -38,6 +39,8 @@ cmain(void)
ideinit(); // disk ideinit(); // disk
#endif #endif
inituser(); // first user process
cprintf("ncpu %d\n", ncpu); cprintf("ncpu %d\n", ncpu);
panic("end"); panic("end");
} }
...@@ -8,10 +8,16 @@ ...@@ -8,10 +8,16 @@
#include "condvar.h" #include "condvar.h"
#include "queue.h" #include "queue.h"
#include "proc.h" #include "proc.h"
#include "cpu.h"
#include "bits.h"
#include "xv6-mtrace.h"
extern void trapret(void);
int __mpalign__ idle[NCPU]; int __mpalign__ idle[NCPU];
struct ns *nspid __mpalign__; struct ns *nspid __mpalign__;
struct ns *nsrunq __mpalign__; struct ns *nsrunq __mpalign__;
static struct proc *bootproc __mpalign__;
void void
sched(void) sched(void)
...@@ -25,6 +31,127 @@ addrun(struct proc *p) ...@@ -25,6 +31,127 @@ addrun(struct proc *p)
panic("addrun"); panic("addrun");
} }
// A fork child's very first scheduling by scheduler()
// will swtch here. "Return" to user space.
static void
forkret(void)
{
// Still holding proc->lock from scheduler.
release(&myproc()->lock);
// Just for the first process. can't do it earlier
// b/c file system code needs a process context
// in which to call cv_sleep().
if(myproc()->cwd == 0) {
mtrace_kstack_start(forkret, myproc());
myproc()->cwd = namei("/");
mtrace_kstack_stop(myproc());
}
// Return to "caller", actually trapret (see allocproc).
}
// Look in the process table for an UNUSED proc.
// If found, change state to EMBRYO and initialize
// state required to run in the kernel.
// Otherwise return 0.
static struct proc*
allocproc(void)
{
struct proc *p;
char *sp;
p = kmalloc(sizeof(struct proc));
if (p == 0) return 0;
memset(p, 0, sizeof(*p));
p->state = EMBRYO;
p->pid = ns_allockey(nspid);
p->epoch = INF;
p->cpuid = mycpu()->id;
p->on_runq = -1;
p->cpu_pin = 0;
p->mtrace_stacks.curr = -1;
snprintf(p->lockname, sizeof(p->lockname), "cv:proc:%d", p->pid);
initlock(&p->lock, p->lockname+3);
initcondvar(&p->cv, p->lockname);
if (ns_insert(nspid, KI(p->pid), (void *) p) < 0)
panic("allocproc: ns_insert");
// Allocate kernel stack if possible.
if((p->kstack = kalloc()) == 0){
if (ns_remove(nspid, KI(p->pid), p) == 0)
panic("allocproc: ns_remove");
rcu_delayed(p, kmfree);
return 0;
}
sp = p->kstack + KSTACKSIZE;
// Leave room for trap frame.
sp -= sizeof *p->tf;
p->tf = (struct trapframe*)sp;
// Set up new context to start executing at forkret,
// which returns to trapret.
sp -= 8;
*(u64*)sp = (u64)trapret;
sp -= sizeof *p->context;
p->context = (struct context*)sp;
memset(p->context, 0, sizeof *p->context);
p->context->rip = (uptr)forkret;
return p;
}
// Set up first user process.
void
inituser(void)
{
struct proc *p;
extern char _binary_initcode_start[], _binary_initcode_size[];
p = allocproc();
bootproc = p;
if((p->vmap = vmap_alloc()) == 0)
panic("userinit: out of vmaps?");
struct vmnode *vmn =
vmn_allocpg(PGROUNDUP((uptr)_binary_initcode_size) / PGSIZE);
if(vmn == 0)
panic("userinit: vmn_allocpg");
if(vmap_insert(p->vmap, vmn, 0) < 0)
panic("userinit: vmap_insert");
if(copyout(p->vmap, 0, _binary_initcode_start, (uptr)_binary_initcode_size) < 0)
panic("userinit: copyout");
memset(p->tf, 0, sizeof(*p->tf));
p->tf->rflags = FL_IF;
p->tf->rsp = PGSIZE;
p->tf->rip = 0; // beginning of initcode.S
safestrcpy(p->name, "initcode", sizeof(p->name));
p->cwd = 0; // forkret will fix in the process's context
acquire(&p->lock);
addrun(p);
p->state = RUNNABLE;
release(&p->lock);
for (u32 c = 0; c < NCPU; c++) {
struct proc *rcup = allocproc();
rcup->vmap = vmap_alloc();
rcup->context->rip = (u64) rcu_gc_worker;
rcup->cwd = 0;
rcup->cpuid = c;
rcup->cpu_pin = 1;
acquire(&rcup->lock);
rcup->state = RUNNABLE;
addrun(rcup);
release(&rcup->lock);
}
}
void void
initproc(void) initproc(void)
{ {
...@@ -115,7 +242,7 @@ allocproc(void) ...@@ -115,7 +242,7 @@ allocproc(void)
// Set up new context to start executing at forkret, // Set up new context to start executing at forkret,
// which returns to trapret. // which returns to trapret.
sp -= 4; sp -= 8;
*(uint*)sp = (uint)trapret; *(uint*)sp = (uint)trapret;
sp -= sizeof *p->context; sp -= sizeof *p->context;
......
#include "spinlock.h" #include "spinlock.h"
// Saved registers for kernel context switches.
struct context {
u64 rip;
};
// Per-process, per-stack meta data for mtrace // Per-process, per-stack meta data for mtrace
#define MTRACE_NSTACKS 16 #define MTRACE_NSTACKS 16
#define MTRACE_TAGSHIFT 28 #define MTRACE_TAGSHIFT 28
......
...@@ -17,26 +17,45 @@ ...@@ -17,26 +17,45 @@
trappush: trappush:
pushq $0 // error code pushq $0 // error code
trapcommon: trapcommon:
// TODO(rsc): Do we need to push ds, es, fs, gs? pushq %rdi
pushq %r15 pushq %rsi
pushq %r14 pushq %rdx
pushq %r13 pushq %rcx
pushq %r12 pushq %rax
pushq %r11 pushq %r8
pushq %r10 pushq %r9
pushq %r9 pushq %r10
pushq %r8 pushq %r11
pushq %rdi pushq %rbx
pushq %rsi pushq %rbp
pushq %rbp pushq %r12
pushq $0 // sp pushq %r13
pushq %rbx pushq %r14
pushq %rdx pushq %r15
pushq %rcx
pushq %rax
movq %rsp, %rdi // first argument to trap movq %rsp, %rdi // first argument to trap
call trap call trap
.globl trapret
.align 8
trapret:
popq %r15
popq %r14
popq %r13
popq %r12
popq %rbp
popq %rbx
popq %r11
popq %r10
popq %r9
popq %r8
popq %rax
popq %rcx
popq %rdx
popq %rsi
popq %rdi
addq $0x12, %rsp // trapno, err
iret
.data .data
.align 8 .align 8
.globl trapentry .globl trapentry
......
...@@ -103,3 +103,38 @@ writemsr(u32 msr, u64 val) ...@@ -103,3 +103,38 @@ writemsr(u32 msr, u64 val)
u32 hi = val >> 32; u32 hi = val >> 32;
__asm volatile("wrmsr" : : "c" (msr), "a" (lo), "d" (hi)); __asm volatile("wrmsr" : : "c" (msr), "a" (lo), "d" (hi));
} }
// Layout of the trap frame built on the stack by the
// hardware and by trapasm.S, and passed to trap().
struct trapframe {
u64 r15;
u64 r14;
u64 r13;
u64 r12;
u64 rbp;
u64 rbx;
// amd64 ABI callee saved registers
u64 r11;
u64 r10;
u64 r9;
u64 r8;
u64 rax;
u64 rcx;
u64 rdx;
u64 rsi;
u64 rdi;
u64 trapno;
// Below here defined by amd64 hardware
u32 err;
u16 padding2[2];
u64 rip;
u16 cs;
u16 padding1[3];
u64 rflags;
// Unlike 32-bit, amd64 hardware always pushes below
u64 rsp;
u16 ss;
u16 padding0[3];
} __attribute__((packed));
...@@ -21,4 +21,5 @@ char* strncpy(char *s, const char *t, int n); ...@@ -21,4 +21,5 @@ char* strncpy(char *s, const char *t, int n);
#define mtrace_lock_register(ip, x, name, op, y) #define mtrace_lock_register(ip, x, name, op, y)
#define mtrace_label_register(t, r, x, y, z, ip) #define mtrace_label_register(t, r, x, y, z, ip)
#define mtrace_kstack_start(x, y) #define mtrace_kstack_start(x, y)
#define mtrace_kstack_stop(x)
#endif #endif
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论