Merge branch 'nogs'
This commit is contained in:
commit
61cb32aa9b
|
@ -111,7 +111,8 @@ panic(char *s)
|
||||||
|
|
||||||
cli();
|
cli();
|
||||||
cons.locking = 0;
|
cons.locking = 0;
|
||||||
cprintf("cpu with apicid %d: panic: ", cpu->apicid);
|
// use lapiccpunum so that we can call panic from mycpu()
|
||||||
|
cprintf("lapicid %d: panic: ", lapicid());
|
||||||
cprintf(s);
|
cprintf(s);
|
||||||
cprintf("\n");
|
cprintf("\n");
|
||||||
getcallerpcs(&s, pcs);
|
getcallerpcs(&s, pcs);
|
||||||
|
@ -242,7 +243,7 @@ consoleread(struct inode *ip, char *dst, int n)
|
||||||
acquire(&cons.lock);
|
acquire(&cons.lock);
|
||||||
while(n > 0){
|
while(n > 0){
|
||||||
while(input.r == input.w){
|
while(input.r == input.w){
|
||||||
if(proc->killed){
|
if(myproc()->killed){
|
||||||
release(&cons.lock);
|
release(&cons.lock);
|
||||||
ilock(ip);
|
ilock(ip);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
6
defs.h
6
defs.h
|
@ -74,7 +74,7 @@ void kbdintr(void);
|
||||||
|
|
||||||
// lapic.c
|
// lapic.c
|
||||||
void cmostime(struct rtcdate *r);
|
void cmostime(struct rtcdate *r);
|
||||||
int cpunum(void);
|
int lapicid(void);
|
||||||
extern volatile uint* lapic;
|
extern volatile uint* lapic;
|
||||||
void lapiceoi(void);
|
void lapiceoi(void);
|
||||||
void lapicinit(void);
|
void lapicinit(void);
|
||||||
|
@ -103,14 +103,18 @@ int pipewrite(struct pipe*, char*, int);
|
||||||
|
|
||||||
//PAGEBREAK: 16
|
//PAGEBREAK: 16
|
||||||
// proc.c
|
// proc.c
|
||||||
|
int cpuid(void);
|
||||||
void exit(void);
|
void exit(void);
|
||||||
int fork(void);
|
int fork(void);
|
||||||
int growproc(int);
|
int growproc(int);
|
||||||
int kill(int);
|
int kill(int);
|
||||||
|
struct cpu* mycpu(void);
|
||||||
|
struct proc* myproc();
|
||||||
void pinit(void);
|
void pinit(void);
|
||||||
void procdump(void);
|
void procdump(void);
|
||||||
void scheduler(void) __attribute__((noreturn));
|
void scheduler(void) __attribute__((noreturn));
|
||||||
void sched(void);
|
void sched(void);
|
||||||
|
void setproc(struct proc*);
|
||||||
void sleep(void*, struct spinlock*);
|
void sleep(void*, struct spinlock*);
|
||||||
void userinit(void);
|
void userinit(void);
|
||||||
int wait(void);
|
int wait(void);
|
||||||
|
|
16
exec.c
16
exec.c
|
@ -17,11 +17,13 @@ exec(char *path, char **argv)
|
||||||
struct inode *ip;
|
struct inode *ip;
|
||||||
struct proghdr ph;
|
struct proghdr ph;
|
||||||
pde_t *pgdir, *oldpgdir;
|
pde_t *pgdir, *oldpgdir;
|
||||||
|
struct proc *curproc = myproc();
|
||||||
|
|
||||||
begin_op();
|
begin_op();
|
||||||
|
|
||||||
if((ip = namei(path)) == 0){
|
if((ip = namei(path)) == 0){
|
||||||
end_op();
|
end_op();
|
||||||
|
cprintf("exec: fail\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ilock(ip);
|
ilock(ip);
|
||||||
|
@ -89,15 +91,15 @@ exec(char *path, char **argv)
|
||||||
for(last=s=path; *s; s++)
|
for(last=s=path; *s; s++)
|
||||||
if(*s == '/')
|
if(*s == '/')
|
||||||
last = s+1;
|
last = s+1;
|
||||||
safestrcpy(proc->name, last, sizeof(proc->name));
|
safestrcpy(curproc->name, last, sizeof(curproc->name));
|
||||||
|
|
||||||
// Commit to the user image.
|
// Commit to the user image.
|
||||||
oldpgdir = proc->pgdir;
|
oldpgdir = curproc->pgdir;
|
||||||
proc->pgdir = pgdir;
|
curproc->pgdir = pgdir;
|
||||||
proc->sz = sz;
|
curproc->sz = sz;
|
||||||
proc->tf->eip = elf.entry; // main
|
curproc->tf->eip = elf.entry; // main
|
||||||
proc->tf->esp = sp;
|
curproc->tf->esp = sp;
|
||||||
switchuvm(proc);
|
switchuvm(curproc);
|
||||||
freevm(oldpgdir);
|
freevm(oldpgdir);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
2
fs.c
2
fs.c
|
@ -615,7 +615,7 @@ namex(char *path, int nameiparent, char *name)
|
||||||
if(*path == '/')
|
if(*path == '/')
|
||||||
ip = iget(ROOTDEV, ROOTINO);
|
ip = iget(ROOTDEV, ROOTINO);
|
||||||
else
|
else
|
||||||
ip = idup(proc->cwd);
|
ip = idup(myproc()->cwd);
|
||||||
|
|
||||||
while((path = skipelem(path, name)) != 0){
|
while((path = skipelem(path, name)) != 0){
|
||||||
ilock(ip);
|
ilock(ip);
|
||||||
|
|
3
ide.c
3
ide.c
|
@ -108,9 +108,9 @@ ideintr(void)
|
||||||
|
|
||||||
// First queued buffer is the active request.
|
// First queued buffer is the active request.
|
||||||
acquire(&idelock);
|
acquire(&idelock);
|
||||||
|
|
||||||
if((b = idequeue) == 0){
|
if((b = idequeue) == 0){
|
||||||
release(&idelock);
|
release(&idelock);
|
||||||
// cprintf("spurious IDE interrupt\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
idequeue = b->qnext;
|
idequeue = b->qnext;
|
||||||
|
@ -164,5 +164,6 @@ iderw(struct buf *b)
|
||||||
sleep(b, &idelock);
|
sleep(b, &idelock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
release(&idelock);
|
release(&idelock);
|
||||||
}
|
}
|
||||||
|
|
25
lapic.c
25
lapic.c
|
@ -9,7 +9,6 @@
|
||||||
#include "traps.h"
|
#include "traps.h"
|
||||||
#include "mmu.h"
|
#include "mmu.h"
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
#include "proc.h" // ncpu
|
|
||||||
|
|
||||||
// Local APIC registers, divided by 4 for use as uint[] indices.
|
// Local APIC registers, divided by 4 for use as uint[] indices.
|
||||||
#define ID (0x0020/4) // ID
|
#define ID (0x0020/4) // ID
|
||||||
|
@ -99,31 +98,11 @@ lapicinit(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
cpunum(void)
|
lapicid(void)
|
||||||
{
|
{
|
||||||
int apicid, i;
|
|
||||||
|
|
||||||
// Cannot call cpu when interrupts are enabled:
|
|
||||||
// result not guaranteed to last long enough to be used!
|
|
||||||
// Would prefer to panic but even printing is chancy here:
|
|
||||||
// almost everything, including cprintf and panic, calls cpu,
|
|
||||||
// often indirectly through acquire and release.
|
|
||||||
if(readeflags()&FL_IF){
|
|
||||||
static int n;
|
|
||||||
if(n++ == 0)
|
|
||||||
cprintf("cpu called from %x with interrupts enabled\n",
|
|
||||||
__builtin_return_address(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lapic)
|
if (!lapic)
|
||||||
return 0;
|
return 0;
|
||||||
|
return lapic[ID] >> 24;
|
||||||
apicid = lapic[ID] >> 24;
|
|
||||||
for (i = 0; i < ncpu; ++i) {
|
|
||||||
if (cpus[i].apicid == apicid)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
panic("unknown apicid\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Acknowledge interrupt.
|
// Acknowledge interrupt.
|
||||||
|
|
7
main.c
7
main.c
|
@ -22,7 +22,6 @@ main(void)
|
||||||
mpinit(); // detect other processors
|
mpinit(); // detect other processors
|
||||||
lapicinit(); // interrupt controller
|
lapicinit(); // interrupt controller
|
||||||
seginit(); // segment descriptors
|
seginit(); // segment descriptors
|
||||||
cprintf("\ncpu%d: starting xv6\n\n", cpunum());
|
|
||||||
picinit(); // another interrupt controller
|
picinit(); // another interrupt controller
|
||||||
ioapicinit(); // another interrupt controller
|
ioapicinit(); // another interrupt controller
|
||||||
consoleinit(); // console hardware
|
consoleinit(); // console hardware
|
||||||
|
@ -54,9 +53,9 @@ mpenter(void)
|
||||||
static void
|
static void
|
||||||
mpmain(void)
|
mpmain(void)
|
||||||
{
|
{
|
||||||
cprintf("cpu%d: starting\n", cpunum());
|
cprintf("cpu%d: starting %d\n", cpuid(), cpuid());
|
||||||
idtinit(); // load idt register
|
idtinit(); // load idt register
|
||||||
xchg(&cpu->started, 1); // tell startothers() we're up
|
xchg(&(mycpu()->started), 1); // tell startothers() we're up
|
||||||
scheduler(); // start running processes
|
scheduler(); // start running processes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +77,7 @@ startothers(void)
|
||||||
memmove(code, _binary_entryother_start, (uint)_binary_entryother_size);
|
memmove(code, _binary_entryother_start, (uint)_binary_entryother_size);
|
||||||
|
|
||||||
for(c = cpus; c < cpus+ncpu; c++){
|
for(c = cpus; c < cpus+ncpu; c++){
|
||||||
if(c == cpus+cpunum()) // We've started already.
|
if(c == mycpu()) // We've started already.
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Tell entryother.S what stack to use, where to enter, and what
|
// Tell entryother.S what stack to use, where to enter, and what
|
||||||
|
|
9
mmu.h
9
mmu.h
|
@ -42,13 +42,12 @@
|
||||||
// various segment selectors.
|
// various segment selectors.
|
||||||
#define SEG_KCODE 1 // kernel code
|
#define SEG_KCODE 1 // kernel code
|
||||||
#define SEG_KDATA 2 // kernel data+stack
|
#define SEG_KDATA 2 // kernel data+stack
|
||||||
#define SEG_KCPU 3 // kernel per-cpu data
|
#define SEG_UCODE 3 // user code
|
||||||
#define SEG_UCODE 4 // user code
|
#define SEG_UDATA 4 // user data+stack
|
||||||
#define SEG_UDATA 5 // user data+stack
|
#define SEG_TSS 5 // this process's task state
|
||||||
#define SEG_TSS 6 // this process's task state
|
|
||||||
|
|
||||||
// cpu->gdt[NSEGS] holds the above segments.
|
// cpu->gdt[NSEGS] holds the above segments.
|
||||||
#define NSEGS 7
|
#define NSEGS 6
|
||||||
|
|
||||||
//PAGEBREAK!
|
//PAGEBREAK!
|
||||||
#ifndef __ASSEMBLER__
|
#ifndef __ASSEMBLER__
|
||||||
|
|
4
pipe.c
4
pipe.c
|
@ -83,7 +83,7 @@ pipewrite(struct pipe *p, char *addr, int n)
|
||||||
acquire(&p->lock);
|
acquire(&p->lock);
|
||||||
for(i = 0; i < n; i++){
|
for(i = 0; i < n; i++){
|
||||||
while(p->nwrite == p->nread + PIPESIZE){ //DOC: pipewrite-full
|
while(p->nwrite == p->nread + PIPESIZE){ //DOC: pipewrite-full
|
||||||
if(p->readopen == 0 || proc->killed){
|
if(p->readopen == 0 || myproc()->killed){
|
||||||
release(&p->lock);
|
release(&p->lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ piperead(struct pipe *p, char *addr, int n)
|
||||||
|
|
||||||
acquire(&p->lock);
|
acquire(&p->lock);
|
||||||
while(p->nread == p->nwrite && p->writeopen){ //DOC: pipe-empty
|
while(p->nread == p->nwrite && p->writeopen){ //DOC: pipe-empty
|
||||||
if(proc->killed){
|
if(myproc()->killed){
|
||||||
release(&p->lock);
|
release(&p->lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
129
proc.c
129
proc.c
|
@ -26,6 +26,45 @@ pinit(void)
|
||||||
initlock(&ptable.lock, "ptable");
|
initlock(&ptable.lock, "ptable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Must be called with interrupts disabled
|
||||||
|
int
|
||||||
|
cpuid() {
|
||||||
|
return mycpu()-cpus;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must be called with interrupts disabled to avoid the caller being rescheduled
|
||||||
|
// between reading lapicid and running through the loop.
|
||||||
|
struct cpu*
|
||||||
|
mycpu(void)
|
||||||
|
{
|
||||||
|
int apicid, i;
|
||||||
|
|
||||||
|
if(readeflags()&FL_IF)
|
||||||
|
panic("mycpu called with interrupts enabled\n");
|
||||||
|
|
||||||
|
apicid = lapicid();
|
||||||
|
// APIC IDs are not guaranteed to be contiguous. Maybe we should have
|
||||||
|
// a reverse map, or reserve a register to store &cpus[i].
|
||||||
|
for (i = 0; i < ncpu; ++i) {
|
||||||
|
if (cpus[i].apicid == apicid)
|
||||||
|
return &cpus[i];
|
||||||
|
}
|
||||||
|
panic("unknown apicid\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable interrupts so that we are not rescheduled
|
||||||
|
// while reading proc from the cpu structure
|
||||||
|
struct proc*
|
||||||
|
myproc(void) {
|
||||||
|
struct cpu *c;
|
||||||
|
struct proc *p;
|
||||||
|
pushcli();
|
||||||
|
c = mycpu();
|
||||||
|
p = c->proc;
|
||||||
|
popcli();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
//PAGEBREAK: 32
|
//PAGEBREAK: 32
|
||||||
// Look in the process table for an UNUSED proc.
|
// Look in the process table for an UNUSED proc.
|
||||||
// If found, change state to EMBRYO and initialize
|
// If found, change state to EMBRYO and initialize
|
||||||
|
@ -120,17 +159,18 @@ int
|
||||||
growproc(int n)
|
growproc(int n)
|
||||||
{
|
{
|
||||||
uint sz;
|
uint sz;
|
||||||
|
struct proc *curproc = myproc();
|
||||||
|
|
||||||
sz = proc->sz;
|
sz = curproc->sz;
|
||||||
if(n > 0){
|
if(n > 0){
|
||||||
if((sz = allocuvm(proc->pgdir, sz, sz + n)) == 0)
|
if((sz = allocuvm(curproc->pgdir, sz, sz + n)) == 0)
|
||||||
return -1;
|
return -1;
|
||||||
} else if(n < 0){
|
} else if(n < 0){
|
||||||
if((sz = deallocuvm(proc->pgdir, sz, sz + n)) == 0)
|
if((sz = deallocuvm(curproc->pgdir, sz, sz + n)) == 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
proc->sz = sz;
|
curproc->sz = sz;
|
||||||
switchuvm(proc);
|
switchuvm(curproc);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,32 +182,33 @@ fork(void)
|
||||||
{
|
{
|
||||||
int i, pid;
|
int i, pid;
|
||||||
struct proc *np;
|
struct proc *np;
|
||||||
|
struct proc *curproc = myproc();
|
||||||
|
|
||||||
// Allocate process.
|
// Allocate process.
|
||||||
if((np = allocproc()) == 0){
|
if((np = allocproc()) == 0){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy process state from p.
|
// Copy process state from proc.
|
||||||
if((np->pgdir = copyuvm(proc->pgdir, proc->sz)) == 0){
|
if((np->pgdir = copyuvm(curproc->pgdir, curproc->sz)) == 0){
|
||||||
kfree(np->kstack);
|
kfree(np->kstack);
|
||||||
np->kstack = 0;
|
np->kstack = 0;
|
||||||
np->state = UNUSED;
|
np->state = UNUSED;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
np->sz = proc->sz;
|
np->sz = curproc->sz;
|
||||||
np->parent = proc;
|
np->parent = curproc;
|
||||||
*np->tf = *proc->tf;
|
*np->tf = *curproc->tf;
|
||||||
|
|
||||||
// Clear %eax so that fork returns 0 in the child.
|
// Clear %eax so that fork returns 0 in the child.
|
||||||
np->tf->eax = 0;
|
np->tf->eax = 0;
|
||||||
|
|
||||||
for(i = 0; i < NOFILE; i++)
|
for(i = 0; i < NOFILE; i++)
|
||||||
if(proc->ofile[i])
|
if(curproc->ofile[i])
|
||||||
np->ofile[i] = filedup(proc->ofile[i]);
|
np->ofile[i] = filedup(curproc->ofile[i]);
|
||||||
np->cwd = idup(proc->cwd);
|
np->cwd = idup(curproc->cwd);
|
||||||
|
|
||||||
safestrcpy(np->name, proc->name, sizeof(proc->name));
|
safestrcpy(np->name, curproc->name, sizeof(curproc->name));
|
||||||
|
|
||||||
pid = np->pid;
|
pid = np->pid;
|
||||||
|
|
||||||
|
@ -186,33 +227,34 @@ fork(void)
|
||||||
void
|
void
|
||||||
exit(void)
|
exit(void)
|
||||||
{
|
{
|
||||||
|
struct proc *curproc = myproc();
|
||||||
struct proc *p;
|
struct proc *p;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if(proc == initproc)
|
if(curproc == initproc)
|
||||||
panic("init exiting");
|
panic("init exiting");
|
||||||
|
|
||||||
// Close all open files.
|
// Close all open files.
|
||||||
for(fd = 0; fd < NOFILE; fd++){
|
for(fd = 0; fd < NOFILE; fd++){
|
||||||
if(proc->ofile[fd]){
|
if(curproc->ofile[fd]){
|
||||||
fileclose(proc->ofile[fd]);
|
fileclose(curproc->ofile[fd]);
|
||||||
proc->ofile[fd] = 0;
|
curproc->ofile[fd] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
begin_op();
|
begin_op();
|
||||||
iput(proc->cwd);
|
iput(curproc->cwd);
|
||||||
end_op();
|
end_op();
|
||||||
proc->cwd = 0;
|
curproc->cwd = 0;
|
||||||
|
|
||||||
acquire(&ptable.lock);
|
acquire(&ptable.lock);
|
||||||
|
|
||||||
// Parent might be sleeping in wait().
|
// Parent might be sleeping in wait().
|
||||||
wakeup1(proc->parent);
|
wakeup1(curproc->parent);
|
||||||
|
|
||||||
// Pass abandoned children to init.
|
// Pass abandoned children to init.
|
||||||
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
|
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
|
||||||
if(p->parent == proc){
|
if(p->parent == curproc){
|
||||||
p->parent = initproc;
|
p->parent = initproc;
|
||||||
if(p->state == ZOMBIE)
|
if(p->state == ZOMBIE)
|
||||||
wakeup1(initproc);
|
wakeup1(initproc);
|
||||||
|
@ -220,7 +262,7 @@ exit(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jump into the scheduler, never to return.
|
// Jump into the scheduler, never to return.
|
||||||
proc->state = ZOMBIE;
|
curproc->state = ZOMBIE;
|
||||||
sched();
|
sched();
|
||||||
panic("zombie exit");
|
panic("zombie exit");
|
||||||
}
|
}
|
||||||
|
@ -232,13 +274,14 @@ wait(void)
|
||||||
{
|
{
|
||||||
struct proc *p;
|
struct proc *p;
|
||||||
int havekids, pid;
|
int havekids, pid;
|
||||||
|
struct proc *curproc = myproc();
|
||||||
|
|
||||||
acquire(&ptable.lock);
|
acquire(&ptable.lock);
|
||||||
for(;;){
|
for(;;){
|
||||||
// Scan through table looking for exited children.
|
// Scan through table looking for exited children.
|
||||||
havekids = 0;
|
havekids = 0;
|
||||||
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
|
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
|
||||||
if(p->parent != proc)
|
if(p->parent != curproc)
|
||||||
continue;
|
continue;
|
||||||
havekids = 1;
|
havekids = 1;
|
||||||
if(p->state == ZOMBIE){
|
if(p->state == ZOMBIE){
|
||||||
|
@ -258,13 +301,13 @@ wait(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// No point waiting if we don't have any children.
|
// No point waiting if we don't have any children.
|
||||||
if(!havekids || proc->killed){
|
if(!havekids || curproc->killed){
|
||||||
release(&ptable.lock);
|
release(&ptable.lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for children to exit. (See wakeup1 call in proc_exit.)
|
// Wait for children to exit. (See wakeup1 call in proc_exit.)
|
||||||
sleep(proc, &ptable.lock); //DOC: wait-sleep
|
sleep(curproc, &ptable.lock); //DOC: wait-sleep
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,6 +323,8 @@ void
|
||||||
scheduler(void)
|
scheduler(void)
|
||||||
{
|
{
|
||||||
struct proc *p;
|
struct proc *p;
|
||||||
|
struct cpu *c = mycpu();
|
||||||
|
c->proc = 0;
|
||||||
|
|
||||||
for(;;){
|
for(;;){
|
||||||
// Enable interrupts on this processor.
|
// Enable interrupts on this processor.
|
||||||
|
@ -294,15 +339,16 @@ scheduler(void)
|
||||||
// Switch to chosen process. It is the process's job
|
// Switch to chosen process. It is the process's job
|
||||||
// to release ptable.lock and then reacquire it
|
// to release ptable.lock and then reacquire it
|
||||||
// before jumping back to us.
|
// before jumping back to us.
|
||||||
proc = p;
|
c->proc = p;
|
||||||
switchuvm(p);
|
switchuvm(p);
|
||||||
p->state = RUNNING;
|
p->state = RUNNING;
|
||||||
swtch(&cpu->scheduler, p->context);
|
|
||||||
|
swtch(&(c->scheduler), p->context);
|
||||||
switchkvm();
|
switchkvm();
|
||||||
|
|
||||||
// Process is done running for now.
|
// Process is done running for now.
|
||||||
// It should have changed its p->state before coming back.
|
// It should have changed its p->state before coming back.
|
||||||
proc = 0;
|
c->proc = 0;
|
||||||
}
|
}
|
||||||
release(&ptable.lock);
|
release(&ptable.lock);
|
||||||
|
|
||||||
|
@ -320,18 +366,19 @@ void
|
||||||
sched(void)
|
sched(void)
|
||||||
{
|
{
|
||||||
int intena;
|
int intena;
|
||||||
|
struct proc *p = myproc();
|
||||||
|
|
||||||
if(!holding(&ptable.lock))
|
if(!holding(&ptable.lock))
|
||||||
panic("sched ptable.lock");
|
panic("sched ptable.lock");
|
||||||
if(cpu->ncli != 1)
|
if(mycpu()->ncli != 1)
|
||||||
panic("sched locks");
|
panic("sched locks");
|
||||||
if(proc->state == RUNNING)
|
if(p->state == RUNNING)
|
||||||
panic("sched running");
|
panic("sched running");
|
||||||
if(readeflags()&FL_IF)
|
if(readeflags()&FL_IF)
|
||||||
panic("sched interruptible");
|
panic("sched interruptible");
|
||||||
intena = cpu->intena;
|
intena = mycpu()->intena;
|
||||||
swtch(&proc->context, cpu->scheduler);
|
swtch(&p->context, mycpu()->scheduler);
|
||||||
cpu->intena = intena;
|
mycpu()->intena = intena;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give up the CPU for one scheduling round.
|
// Give up the CPU for one scheduling round.
|
||||||
|
@ -339,7 +386,7 @@ void
|
||||||
yield(void)
|
yield(void)
|
||||||
{
|
{
|
||||||
acquire(&ptable.lock); //DOC: yieldlock
|
acquire(&ptable.lock); //DOC: yieldlock
|
||||||
proc->state = RUNNABLE;
|
myproc()->state = RUNNABLE;
|
||||||
sched();
|
sched();
|
||||||
release(&ptable.lock);
|
release(&ptable.lock);
|
||||||
}
|
}
|
||||||
|
@ -370,7 +417,9 @@ forkret(void)
|
||||||
void
|
void
|
||||||
sleep(void *chan, struct spinlock *lk)
|
sleep(void *chan, struct spinlock *lk)
|
||||||
{
|
{
|
||||||
if(proc == 0)
|
struct proc *p = myproc();
|
||||||
|
|
||||||
|
if(p == 0)
|
||||||
panic("sleep");
|
panic("sleep");
|
||||||
|
|
||||||
if(lk == 0)
|
if(lk == 0)
|
||||||
|
@ -386,14 +435,14 @@ sleep(void *chan, struct spinlock *lk)
|
||||||
acquire(&ptable.lock); //DOC: sleeplock1
|
acquire(&ptable.lock); //DOC: sleeplock1
|
||||||
release(lk);
|
release(lk);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go to sleep.
|
// Go to sleep.
|
||||||
proc->chan = chan;
|
p->chan = chan;
|
||||||
proc->state = SLEEPING;
|
p->state = SLEEPING;
|
||||||
|
|
||||||
sched();
|
sched();
|
||||||
|
|
||||||
// Tidy up.
|
// Tidy up.
|
||||||
proc->chan = 0;
|
p->chan = 0;
|
||||||
|
|
||||||
// Reacquire original lock.
|
// Reacquire original lock.
|
||||||
if(lk != &ptable.lock){ //DOC: sleeplock2
|
if(lk != &ptable.lock){ //DOC: sleeplock2
|
||||||
|
|
16
proc.h
16
proc.h
|
@ -7,26 +7,12 @@ struct cpu {
|
||||||
volatile uint started; // Has the CPU started?
|
volatile uint started; // Has the CPU started?
|
||||||
int ncli; // Depth of pushcli nesting.
|
int ncli; // Depth of pushcli nesting.
|
||||||
int intena; // Were interrupts enabled before pushcli?
|
int intena; // Were interrupts enabled before pushcli?
|
||||||
|
struct proc *proc; // The process running on this cpu or null
|
||||||
// Cpu-local storage variables; see below
|
|
||||||
struct cpu *cpu;
|
|
||||||
struct proc *proc; // The currently-running process.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct cpu cpus[NCPU];
|
extern struct cpu cpus[NCPU];
|
||||||
extern int ncpu;
|
extern int ncpu;
|
||||||
|
|
||||||
// Per-CPU variables, holding pointers to the
|
|
||||||
// current cpu and to the current process.
|
|
||||||
// The asm suffix tells gcc to use "%gs:0" to refer to cpu
|
|
||||||
// and "%gs:4" to refer to proc. seginit sets up the
|
|
||||||
// %gs segment register so that %gs refers to the memory
|
|
||||||
// holding those two variables in the local cpu's struct cpu.
|
|
||||||
// This is similar to how thread-local variables are implemented
|
|
||||||
// in thread libraries such as Linux pthreads.
|
|
||||||
extern struct cpu *cpu asm("%gs:0"); // &cpus[cpunum()]
|
|
||||||
extern struct proc *proc asm("%gs:4"); // cpus[cpunum()].proc
|
|
||||||
|
|
||||||
//PAGEBREAK: 17
|
//PAGEBREAK: 17
|
||||||
// Saved registers for kernel context switches.
|
// Saved registers for kernel context switches.
|
||||||
// Don't need to save all the segment registers (%cs, etc),
|
// Don't need to save all the segment registers (%cs, etc),
|
||||||
|
|
|
@ -27,7 +27,7 @@ acquiresleep(struct sleeplock *lk)
|
||||||
sleep(lk, &lk->lk);
|
sleep(lk, &lk->lk);
|
||||||
}
|
}
|
||||||
lk->locked = 1;
|
lk->locked = 1;
|
||||||
lk->pid = proc->pid;
|
lk->pid = myproc()->pid;
|
||||||
release(&lk->lk);
|
release(&lk->lk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
spinlock.c
14
spinlock.c
|
@ -38,7 +38,7 @@ acquire(struct spinlock *lk)
|
||||||
__sync_synchronize();
|
__sync_synchronize();
|
||||||
|
|
||||||
// Record info about lock acquisition for debugging.
|
// Record info about lock acquisition for debugging.
|
||||||
lk->cpu = cpu;
|
lk->cpu = mycpu();
|
||||||
getcallerpcs(&lk, lk->pcs);
|
getcallerpcs(&lk, lk->pcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ getcallerpcs(void *v, uint pcs[])
|
||||||
int
|
int
|
||||||
holding(struct spinlock *lock)
|
holding(struct spinlock *lock)
|
||||||
{
|
{
|
||||||
return lock->locked && lock->cpu == cpu;
|
return lock->locked && lock->cpu == mycpu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -104,9 +104,9 @@ pushcli(void)
|
||||||
|
|
||||||
eflags = readeflags();
|
eflags = readeflags();
|
||||||
cli();
|
cli();
|
||||||
if(cpu->ncli == 0)
|
if(mycpu()->ncli == 0)
|
||||||
cpu->intena = eflags & FL_IF;
|
mycpu()->intena = eflags & FL_IF;
|
||||||
cpu->ncli += 1;
|
mycpu()->ncli += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -114,9 +114,9 @@ popcli(void)
|
||||||
{
|
{
|
||||||
if(readeflags()&FL_IF)
|
if(readeflags()&FL_IF)
|
||||||
panic("popcli - interruptible");
|
panic("popcli - interruptible");
|
||||||
if(--cpu->ncli < 0)
|
if(--mycpu()->ncli < 0)
|
||||||
panic("popcli");
|
panic("popcli");
|
||||||
if(cpu->ncli == 0 && cpu->intena)
|
if(mycpu()->ncli == 0 && mycpu()->intena)
|
||||||
sti();
|
sti();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
26
syscall.c
26
syscall.c
|
@ -17,7 +17,9 @@
|
||||||
int
|
int
|
||||||
fetchint(uint addr, int *ip)
|
fetchint(uint addr, int *ip)
|
||||||
{
|
{
|
||||||
if(addr >= proc->sz || addr+4 > proc->sz)
|
struct proc *curproc = myproc();
|
||||||
|
|
||||||
|
if(addr >= curproc->sz || addr+4 > curproc->sz)
|
||||||
return -1;
|
return -1;
|
||||||
*ip = *(int*)(addr);
|
*ip = *(int*)(addr);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -30,14 +32,16 @@ int
|
||||||
fetchstr(uint addr, char **pp)
|
fetchstr(uint addr, char **pp)
|
||||||
{
|
{
|
||||||
char *s, *ep;
|
char *s, *ep;
|
||||||
|
struct proc *curproc = myproc();
|
||||||
|
|
||||||
if(addr >= proc->sz)
|
if(addr >= curproc->sz)
|
||||||
return -1;
|
return -1;
|
||||||
*pp = (char*)addr;
|
*pp = (char*)addr;
|
||||||
ep = (char*)proc->sz;
|
ep = (char*)curproc->sz;
|
||||||
for(s = *pp; s < ep; s++)
|
for(s = *pp; s < ep; s++){
|
||||||
if(*s == 0)
|
if(*s == 0)
|
||||||
return s - *pp;
|
return s - *pp;
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +49,7 @@ fetchstr(uint addr, char **pp)
|
||||||
int
|
int
|
||||||
argint(int n, int *ip)
|
argint(int n, int *ip)
|
||||||
{
|
{
|
||||||
return fetchint(proc->tf->esp + 4 + 4*n, ip);
|
return fetchint((myproc()->tf->esp) + 4 + 4*n, ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the nth word-sized system call argument as a pointer
|
// Fetch the nth word-sized system call argument as a pointer
|
||||||
|
@ -55,10 +59,11 @@ int
|
||||||
argptr(int n, char **pp, int size)
|
argptr(int n, char **pp, int size)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
struct proc *curproc = myproc();
|
||||||
|
|
||||||
if(argint(n, &i) < 0)
|
if(argint(n, &i) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if(size < 0 || (uint)i >= proc->sz || (uint)i+size > proc->sz)
|
if(size < 0 || (uint)i >= curproc->sz || (uint)i+size > curproc->sz)
|
||||||
return -1;
|
return -1;
|
||||||
*pp = (char*)i;
|
*pp = (char*)i;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -127,13 +132,14 @@ void
|
||||||
syscall(void)
|
syscall(void)
|
||||||
{
|
{
|
||||||
int num;
|
int num;
|
||||||
|
struct proc *curproc = myproc();
|
||||||
|
|
||||||
num = proc->tf->eax;
|
num = curproc->tf->eax;
|
||||||
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
|
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
|
||||||
proc->tf->eax = syscalls[num]();
|
curproc->tf->eax = syscalls[num]();
|
||||||
} else {
|
} else {
|
||||||
cprintf("%d %s: unknown sys call %d\n",
|
cprintf("%d %s: unknown sys call %d\n",
|
||||||
proc->pid, proc->name, num);
|
curproc->pid, curproc->name, num);
|
||||||
proc->tf->eax = -1;
|
curproc->tf->eax = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
16
sysfile.c
16
sysfile.c
|
@ -26,7 +26,7 @@ argfd(int n, int *pfd, struct file **pf)
|
||||||
|
|
||||||
if(argint(n, &fd) < 0)
|
if(argint(n, &fd) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if(fd < 0 || fd >= NOFILE || (f=proc->ofile[fd]) == 0)
|
if(fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0)
|
||||||
return -1;
|
return -1;
|
||||||
if(pfd)
|
if(pfd)
|
||||||
*pfd = fd;
|
*pfd = fd;
|
||||||
|
@ -41,10 +41,11 @@ static int
|
||||||
fdalloc(struct file *f)
|
fdalloc(struct file *f)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
struct proc *curproc = myproc();
|
||||||
|
|
||||||
for(fd = 0; fd < NOFILE; fd++){
|
for(fd = 0; fd < NOFILE; fd++){
|
||||||
if(proc->ofile[fd] == 0){
|
if(curproc->ofile[fd] == 0){
|
||||||
proc->ofile[fd] = f;
|
curproc->ofile[fd] = f;
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +98,7 @@ sys_close(void)
|
||||||
|
|
||||||
if(argfd(0, &fd, &f) < 0)
|
if(argfd(0, &fd, &f) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
proc->ofile[fd] = 0;
|
myproc()->ofile[fd] = 0;
|
||||||
fileclose(f);
|
fileclose(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -373,6 +374,7 @@ sys_chdir(void)
|
||||||
{
|
{
|
||||||
char *path;
|
char *path;
|
||||||
struct inode *ip;
|
struct inode *ip;
|
||||||
|
struct proc *curproc = myproc();
|
||||||
|
|
||||||
begin_op();
|
begin_op();
|
||||||
if(argstr(0, &path) < 0 || (ip = namei(path)) == 0){
|
if(argstr(0, &path) < 0 || (ip = namei(path)) == 0){
|
||||||
|
@ -386,9 +388,9 @@ sys_chdir(void)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
iunlock(ip);
|
iunlock(ip);
|
||||||
iput(proc->cwd);
|
iput(curproc->cwd);
|
||||||
end_op();
|
end_op();
|
||||||
proc->cwd = ip;
|
curproc->cwd = ip;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,7 +434,7 @@ sys_pipe(void)
|
||||||
fd0 = -1;
|
fd0 = -1;
|
||||||
if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){
|
if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){
|
||||||
if(fd0 >= 0)
|
if(fd0 >= 0)
|
||||||
proc->ofile[fd0] = 0;
|
myproc()->ofile[fd0] = 0;
|
||||||
fileclose(rf);
|
fileclose(rf);
|
||||||
fileclose(wf);
|
fileclose(wf);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -39,7 +39,7 @@ sys_kill(void)
|
||||||
int
|
int
|
||||||
sys_getpid(void)
|
sys_getpid(void)
|
||||||
{
|
{
|
||||||
return proc->pid;
|
return myproc()->pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -50,7 +50,7 @@ sys_sbrk(void)
|
||||||
|
|
||||||
if(argint(0, &n) < 0)
|
if(argint(0, &n) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
addr = proc->sz;
|
addr = myproc()->sz;
|
||||||
if(growproc(n) < 0)
|
if(growproc(n) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
return addr;
|
return addr;
|
||||||
|
@ -67,7 +67,7 @@ sys_sleep(void)
|
||||||
acquire(&tickslock);
|
acquire(&tickslock);
|
||||||
ticks0 = ticks;
|
ticks0 = ticks;
|
||||||
while(ticks - ticks0 < n){
|
while(ticks - ticks0 < n){
|
||||||
if(proc->killed){
|
if(myproc()->killed){
|
||||||
release(&tickslock);
|
release(&tickslock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
24
trap.c
24
trap.c
|
@ -37,18 +37,18 @@ void
|
||||||
trap(struct trapframe *tf)
|
trap(struct trapframe *tf)
|
||||||
{
|
{
|
||||||
if(tf->trapno == T_SYSCALL){
|
if(tf->trapno == T_SYSCALL){
|
||||||
if(proc->killed)
|
if(myproc()->killed)
|
||||||
exit();
|
exit();
|
||||||
proc->tf = tf;
|
myproc()->tf = tf;
|
||||||
syscall();
|
syscall();
|
||||||
if(proc->killed)
|
if(myproc()->killed)
|
||||||
exit();
|
exit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(tf->trapno){
|
switch(tf->trapno){
|
||||||
case T_IRQ0 + IRQ_TIMER:
|
case T_IRQ0 + IRQ_TIMER:
|
||||||
if(cpunum() == 0){
|
if(cpuid() == 0){
|
||||||
acquire(&tickslock);
|
acquire(&tickslock);
|
||||||
ticks++;
|
ticks++;
|
||||||
wakeup(&ticks);
|
wakeup(&ticks);
|
||||||
|
@ -74,38 +74,38 @@ trap(struct trapframe *tf)
|
||||||
case T_IRQ0 + 7:
|
case T_IRQ0 + 7:
|
||||||
case T_IRQ0 + IRQ_SPURIOUS:
|
case T_IRQ0 + IRQ_SPURIOUS:
|
||||||
cprintf("cpu%d: spurious interrupt at %x:%x\n",
|
cprintf("cpu%d: spurious interrupt at %x:%x\n",
|
||||||
cpunum(), tf->cs, tf->eip);
|
cpuid(), tf->cs, tf->eip);
|
||||||
lapiceoi();
|
lapiceoi();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//PAGEBREAK: 13
|
//PAGEBREAK: 13
|
||||||
default:
|
default:
|
||||||
if(proc == 0 || (tf->cs&3) == 0){
|
if(myproc() == 0 || (tf->cs&3) == 0){
|
||||||
// In kernel, it must be our mistake.
|
// In kernel, it must be our mistake.
|
||||||
cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n",
|
cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n",
|
||||||
tf->trapno, cpunum(), tf->eip, rcr2());
|
tf->trapno, cpuid(), tf->eip, rcr2());
|
||||||
panic("trap");
|
panic("trap");
|
||||||
}
|
}
|
||||||
// In user space, assume process misbehaved.
|
// In user space, assume process misbehaved.
|
||||||
cprintf("pid %d %s: trap %d err %d on cpu %d "
|
cprintf("pid %d %s: trap %d err %d on cpu %d "
|
||||||
"eip 0x%x addr 0x%x--kill proc\n",
|
"eip 0x%x addr 0x%x--kill proc\n",
|
||||||
proc->pid, proc->name, tf->trapno, tf->err, cpunum(), tf->eip,
|
myproc()->pid, myproc()->name, tf->trapno, tf->err, cpuid(), tf->eip,
|
||||||
rcr2());
|
rcr2());
|
||||||
proc->killed = 1;
|
myproc()->killed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force process exit if it has been killed and is in user space.
|
// Force process exit if it has been killed and is in user space.
|
||||||
// (If it is still executing in the kernel, let it keep running
|
// (If it is still executing in the kernel, let it keep running
|
||||||
// until it gets to the regular system call return.)
|
// until it gets to the regular system call return.)
|
||||||
if(proc && proc->killed && (tf->cs&3) == DPL_USER)
|
if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER)
|
||||||
exit();
|
exit();
|
||||||
|
|
||||||
// Force process to give up CPU on clock tick.
|
// Force process to give up CPU on clock tick.
|
||||||
// If interrupts were on while locks held, would need to check nlock.
|
// If interrupts were on while locks held, would need to check nlock.
|
||||||
if(proc && proc->state == RUNNING && tf->trapno == T_IRQ0+IRQ_TIMER)
|
if(myproc() && myproc()->state == RUNNING && tf->trapno == T_IRQ0+IRQ_TIMER)
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
// Check if the process has been killed since we yielded
|
// Check if the process has been killed since we yielded
|
||||||
if(proc && proc->killed && (tf->cs&3) == DPL_USER)
|
if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER)
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,6 @@ alltraps:
|
||||||
movw $(SEG_KDATA<<3), %ax
|
movw $(SEG_KDATA<<3), %ax
|
||||||
movw %ax, %ds
|
movw %ax, %ds
|
||||||
movw %ax, %es
|
movw %ax, %es
|
||||||
movw $(SEG_KCPU<<3), %ax
|
|
||||||
movw %ax, %fs
|
|
||||||
movw %ax, %gs
|
|
||||||
|
|
||||||
# Call trap(tf), where tf=%esp
|
# Call trap(tf), where tf=%esp
|
||||||
pushl %esp
|
pushl %esp
|
||||||
|
|
21
vm.c
21
vm.c
|
@ -21,21 +21,12 @@ seginit(void)
|
||||||
// Cannot share a CODE descriptor for both kernel and user
|
// Cannot share a CODE descriptor for both kernel and user
|
||||||
// because it would have to have DPL_USR, but the CPU forbids
|
// because it would have to have DPL_USR, but the CPU forbids
|
||||||
// an interrupt from CPL=0 to DPL=3.
|
// an interrupt from CPL=0 to DPL=3.
|
||||||
c = &cpus[cpunum()];
|
c = &cpus[cpuid()];
|
||||||
c->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, 0);
|
c->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, 0);
|
||||||
c->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);
|
c->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);
|
||||||
c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, DPL_USER);
|
c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, DPL_USER);
|
||||||
c->gdt[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER);
|
c->gdt[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER);
|
||||||
|
|
||||||
// Map cpu and proc -- these are private per cpu.
|
|
||||||
c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 8, 0);
|
|
||||||
|
|
||||||
lgdt(c->gdt, sizeof(c->gdt));
|
lgdt(c->gdt, sizeof(c->gdt));
|
||||||
loadgs(SEG_KCPU << 3);
|
|
||||||
|
|
||||||
// Initialize cpu-local storage.
|
|
||||||
cpu = c;
|
|
||||||
proc = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the address of the PTE in page table pgdir
|
// Return the address of the PTE in page table pgdir
|
||||||
|
@ -173,13 +164,13 @@ switchuvm(struct proc *p)
|
||||||
panic("switchuvm: no pgdir");
|
panic("switchuvm: no pgdir");
|
||||||
|
|
||||||
pushcli();
|
pushcli();
|
||||||
cpu->gdt[SEG_TSS] = SEG16(STS_T32A, &cpu->ts, sizeof(cpu->ts)-1, 0);
|
mycpu()->gdt[SEG_TSS] = SEG16(STS_T32A, &mycpu()->ts, sizeof(mycpu()->ts)-1, 0);
|
||||||
cpu->gdt[SEG_TSS].s = 0;
|
mycpu()->gdt[SEG_TSS].s = 0;
|
||||||
cpu->ts.ss0 = SEG_KDATA << 3;
|
mycpu()->ts.ss0 = SEG_KDATA << 3;
|
||||||
cpu->ts.esp0 = (uint)p->kstack + KSTACKSIZE;
|
mycpu()->ts.esp0 = (uint)p->kstack + KSTACKSIZE;
|
||||||
// setting IOPL=0 in eflags *and* iomb beyond the tss segment limit
|
// setting IOPL=0 in eflags *and* iomb beyond the tss segment limit
|
||||||
// forbids I/O instructions (e.g., inb and outb) from user space
|
// forbids I/O instructions (e.g., inb and outb) from user space
|
||||||
cpu->ts.iomb = (ushort) 0xFFFF;
|
mycpu()->ts.iomb = (ushort) 0xFFFF;
|
||||||
ltr(SEG_TSS << 3);
|
ltr(SEG_TSS << 3);
|
||||||
lcr3(V2P(p->pgdir)); // switch to process's address space
|
lcr3(V2P(p->pgdir)); // switch to process's address space
|
||||||
popcli();
|
popcli();
|
||||||
|
|
Loading…
Reference in a new issue