Make sysexit and trapret paths the same, so that forkret can return through
either path. This helped tracking down a bug: use 144 instead of 32 to find cs in trapframe so that gs is correctly saved and restored. For good measure update linker script, because newer versions of GCC sometimes places symbols passed end.
This commit is contained in:
parent
322990649b
commit
3bfcaeaf01
|
@ -41,9 +41,10 @@ SECTIONS
|
||||||
.data : {
|
.data : {
|
||||||
*(.data)
|
*(.data)
|
||||||
}
|
}
|
||||||
PROVIDE(edata = .);
|
bss : {
|
||||||
.bss : {
|
PROVIDE(edata = .);
|
||||||
*(.bss)
|
*(.bss)
|
||||||
|
*(COMMON)
|
||||||
|
PROVIDE(end = .);
|
||||||
}
|
}
|
||||||
PROVIDE(end = .);
|
|
||||||
}
|
}
|
||||||
|
|
16
proc.c
16
proc.c
|
@ -6,7 +6,6 @@
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
#include "msr.h"
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct spinlock lock;
|
struct spinlock lock;
|
||||||
|
@ -17,7 +16,11 @@ static struct proc *initproc;
|
||||||
|
|
||||||
int nextpid = 1;
|
int nextpid = 1;
|
||||||
extern void forkret(void);
|
extern void forkret(void);
|
||||||
|
|
||||||
|
// we can return two ways out of the kernel and
|
||||||
|
// for new processes we can choose either way
|
||||||
extern void sysexit(void);
|
extern void sysexit(void);
|
||||||
|
extern void trapret(void);
|
||||||
|
|
||||||
static void wakeup1(void *chan);
|
static void wakeup1(void *chan);
|
||||||
|
|
||||||
|
@ -101,6 +104,10 @@ found:
|
||||||
|
|
||||||
// Leave room for trap frame.
|
// Leave room for trap frame.
|
||||||
sp -= sizeof *p->tf;
|
sp -= sizeof *p->tf;
|
||||||
|
|
||||||
|
if ((uint64) sp % 16)
|
||||||
|
panic("misaligned sp");
|
||||||
|
|
||||||
p->tf = (struct trapframe*)sp;
|
p->tf = (struct trapframe*)sp;
|
||||||
|
|
||||||
// Set up new context to start executing at forkret,
|
// Set up new context to start executing at forkret,
|
||||||
|
@ -132,6 +139,8 @@ userinit(void)
|
||||||
inituvm(p->pgdir, _binary_initcode_start, (uint64)_binary_initcode_size);
|
inituvm(p->pgdir, _binary_initcode_start, (uint64)_binary_initcode_size);
|
||||||
p->sz = PGSIZE;
|
p->sz = PGSIZE;
|
||||||
memset(p->tf, 0, sizeof(*p->tf));
|
memset(p->tf, 0, sizeof(*p->tf));
|
||||||
|
p->tf->cs = UCSEG | 0x3;
|
||||||
|
p->tf->ss = UDSEG | 0x3;
|
||||||
p->tf->r11 = FL_IF;
|
p->tf->r11 = FL_IF;
|
||||||
p->tf->rsp = PGSIZE;
|
p->tf->rsp = PGSIZE;
|
||||||
p->tf->rcx = 0; // beginning of initcode.S
|
p->tf->rcx = 0; // beginning of initcode.S
|
||||||
|
@ -321,12 +330,12 @@ scheduler(void)
|
||||||
{
|
{
|
||||||
struct proc *p;
|
struct proc *p;
|
||||||
struct cpu *c = mycpu();
|
struct cpu *c = mycpu();
|
||||||
|
|
||||||
c->proc = 0;
|
c->proc = 0;
|
||||||
|
|
||||||
for(;;){
|
for(;;){
|
||||||
// Enable interrupts on this processor.
|
// Enable interrupts on this processor.
|
||||||
sti();
|
sti();
|
||||||
|
|
||||||
// Loop over process table looking for process to run.
|
// Loop over process table looking for process to run.
|
||||||
acquire(&ptable.lock);
|
acquire(&ptable.lock);
|
||||||
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
|
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
|
||||||
|
@ -336,7 +345,6 @@ 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.
|
||||||
|
|
||||||
c->proc = p;
|
c->proc = p;
|
||||||
switchuvm(p);
|
switchuvm(p);
|
||||||
p->state = RUNNING;
|
p->state = RUNNING;
|
||||||
|
|
11
trapasm.S
11
trapasm.S
|
@ -22,7 +22,7 @@ alltraps:
|
||||||
push %rbx
|
push %rbx
|
||||||
push %rax
|
push %rax
|
||||||
|
|
||||||
cmpw $KCSEG, 32(%rsp) # compare to saved cs
|
cmpw $KCSEG, 144(%rsp) # compare to saved cs
|
||||||
jz 1f
|
jz 1f
|
||||||
swapgs
|
swapgs
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ alltraps:
|
||||||
.globl trapret
|
.globl trapret
|
||||||
trapret:
|
trapret:
|
||||||
cli
|
cli
|
||||||
cmpw $KCSEG, 32(%rsp) # compare to saved cs
|
cmpw $KCSEG, 144(%rsp) # compare to saved cs
|
||||||
jz 1f
|
jz 1f
|
||||||
swapgs
|
swapgs
|
||||||
|
|
||||||
|
@ -72,12 +72,12 @@ sysentry: # Build trap frame.
|
||||||
movq %rax, %rsp
|
movq %rax, %rsp
|
||||||
movq %gs:0, %rax // restore rax
|
movq %gs:0, %rax // restore rax
|
||||||
|
|
||||||
// push usp
|
// push usp to make a valid trapframe
|
||||||
push $0
|
push $(UDSEG|0x3)
|
||||||
push %gs:8
|
push %gs:8
|
||||||
// safe eflags and eip
|
// safe eflags and eip
|
||||||
push %r11
|
push %r11
|
||||||
push $UCSEG
|
push $(UCSEG|0x3)
|
||||||
push %rcx
|
push %rcx
|
||||||
// push errno and trapno to make stack look like a trap
|
// push errno and trapno to make stack look like a trap
|
||||||
push $0
|
push $0
|
||||||
|
@ -130,6 +130,7 @@ sysexit:
|
||||||
|
|
||||||
add $(5*8), %rsp # discard trapnum, errorcode, rip, cs and rflags
|
add $(5*8), %rsp # discard trapnum, errorcode, rip, cs and rflags
|
||||||
mov (%rsp),%rsp # switch to the user stack
|
mov (%rsp),%rsp # switch to the user stack
|
||||||
|
# there are two more values on the stack, but we don't care about them
|
||||||
swapgs
|
swapgs
|
||||||
|
|
||||||
sysretq
|
sysretq
|
||||||
|
|
Loading…
Reference in a new issue