First pass at Nickolai's exec hack.

I think i got it right..if it's buggy you can disable with EXECSWITCH 0 in param.h.
上级 a6b4886d
...@@ -175,6 +175,7 @@ int pipewrite(struct pipe*, const char*, int); ...@@ -175,6 +175,7 @@ int pipewrite(struct pipe*, const char*, int);
// proc.c // proc.c
struct proc* copyproc(struct proc*); struct proc* copyproc(struct proc*);
void finishproc(struct proc*, bool removepid = true); void finishproc(struct proc*, bool removepid = true);
void execswitch(proc* p);
void exit(void); void exit(void);
int fork(int); int fork(int);
int growproc(int); int growproc(int);
...@@ -219,6 +220,10 @@ int fetchmem(void*, const void*, u64); ...@@ -219,6 +220,10 @@ int fetchmem(void*, const void*, u64);
int putmem(void*, const void*, u64); int putmem(void*, const void*, u64);
u64 syscall(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 num); u64 syscall(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 num);
// sysfile.cc
int doexec(const char* upath,
userptr<userptr<const char> > uargv);
// string.c // string.c
extern "C" int memcmp(const void*, const void*, size_t); extern "C" int memcmp(const void*, const void*, size_t);
void* memmove(void*, const void*, size_t); void* memmove(void*, const void*, size_t);
......
...@@ -84,6 +84,9 @@ struct proc : public rcu_freed, public sched_link { ...@@ -84,6 +84,9 @@ struct proc : public rcu_freed, public sched_link {
int run_cpuid_; int run_cpuid_;
int in_exec_; int in_exec_;
int uaccess_; int uaccess_;
const char *upath;
userptr<userptr<const char> > uargv;
u8 __cxa_eh_global[16]; u8 __cxa_eh_global[16];
std::atomic<int> exception_inuse; std::atomic<int> exception_inuse;
......
...@@ -157,17 +157,6 @@ exec(const char *path, char **argv, void *ascopev) ...@@ -157,17 +157,6 @@ exec(const char *path, char **argv, void *ascopev)
cwork* w; cwork* w;
long sp; long sp;
myproc()->exec_cpuid_ = mycpuid();
mt_ascope *ascope = (mt_ascope*) ascopev;
ascope->close();
myproc()->in_exec_ = 1;
yield();
myproc()->in_exec_ = 0;
ascope->open("sys_exec2(%s)", path);
myproc()->run_cpuid_ = mycpuid();
if((ip = namei(myproc()->cwd, path)) == 0) if((ip = namei(myproc()->cwd, path)) == 0)
return -1; return -1;
......
...@@ -42,6 +42,7 @@ proc::proc(int npid) : ...@@ -42,6 +42,7 @@ proc::proc(int npid) :
ftable(0), cwd(0), tsc(0), curcycles(0), cpuid(0), epoch(0), ftable(0), cwd(0), tsc(0), curcycles(0), cpuid(0), epoch(0),
cpu_pin(0), oncv(0), cv_wakeup(0), cpu_pin(0), oncv(0), cv_wakeup(0),
user_fs_(0), unmap_tlbreq_(0), in_exec_(0), uaccess_(0), user_fs_(0), unmap_tlbreq_(0), in_exec_(0), uaccess_(0),
upath(0), uargv(userptr<const char>(nullptr)),
exception_inuse(0), magic(PROC_MAGIC), state_(EMBRYO) exception_inuse(0), magic(PROC_MAGIC), state_(EMBRYO)
{ {
snprintf(lockname, sizeof(lockname), "cv:proc:%d", pid); snprintf(lockname, sizeof(lockname), "cv:proc:%d", pid);
...@@ -204,6 +205,85 @@ freeproc(struct proc *p) ...@@ -204,6 +205,85 @@ freeproc(struct proc *p)
gc_delayed(p); gc_delayed(p);
} }
void
execstub(void)
{
userptr<userptr<const char> > uargv;
const char* upath;
upath = myproc()->upath;
uargv = myproc()->uargv;
barrier();
myproc()->upath = nullptr;
post_swtch();
myproc()->run_cpuid_ = mycpuid();
long r = doexec(upath, uargv);
myproc()->tf->rax = r;
// This stuff would have been called in syscall and syscall_c
// if we returned from the the previous kstack
mtstop(myproc());
mtign();
if (myproc()->killed) {
mtstart(trap, myproc());
exit();
}
}
static void
kstackfree(void* kstack)
{
ksfree(slab_stack, kstack);
}
void
execswitch(proc* p)
{
// Alloc a new kernel stack, set it up, and free the old one
context* cntxt;
trapframe* tf;
char* kstack;
char* sp;
if ((kstack = (char*) ksalloc(slab_stack)) == 0)
panic("execswitch: ksalloc");
sp = kstack + KSTACKSIZE;
sp -= sizeof(*p->tf);
tf = (trapframe*)sp;
// XXX(sbw) we only need the whole tf if exec fails
*tf = *p->tf;
sp -= 8;
// XXX(sbw) we could use the sysret return path
*(u64*)sp = (u64)trapret;
sp -= sizeof(*p->context);
cntxt = (context*)sp;
memset(cntxt, 0, sizeof(*cntxt));
cntxt->rip = (uptr)execstub;
cwork* w = new cwork();
if (w != nullptr) {
w->rip = (void*) kstackfree;
w->arg0 = p->kstack;
if (wqcrit_push(w, myproc()->exec_cpuid_) < 0) {
ksfree(slab_stack, p->kstack);
delete w;
}
} else {
ksfree(slab_stack, p->kstack);
}
p->kstack = kstack;
p->context = cntxt;
p->tf = tf;
}
proc* proc*
proc::alloc(void) proc::alloc(void)
{ {
......
...@@ -227,7 +227,9 @@ scheddump(void) ...@@ -227,7 +227,9 @@ scheddump(void)
void void
addrun(struct proc* p) addrun(struct proc* p)
{ {
ANON_REGION(__func__, &perfgroup); if (p->upath)
execswitch(p);
p->set_state(RUNNABLE); p->set_state(RUNNABLE);
schedule_[p->cpuid].enq(p); schedule_[p->cpuid].enq(p);
} }
......
...@@ -430,9 +430,8 @@ sys_chdir(const char *path) ...@@ -430,9 +430,8 @@ sys_chdir(const char *path)
return 0; return 0;
} }
//SYSCALL
int int
sys_exec(const char *upath, userptr<userptr<const char> > uargv) doexec(const char* upath, userptr<userptr<const char> > uargv)
{ {
ANON_REGION(__func__, &perfgroup); ANON_REGION(__func__, &perfgroup);
char *argv[MAXARG]; char *argv[MAXARG];
...@@ -459,16 +458,33 @@ sys_exec(const char *upath, userptr<userptr<const char> > uargv) ...@@ -459,16 +458,33 @@ sys_exec(const char *upath, userptr<userptr<const char> > uargv)
if (argv[i]==nullptr || fetchstr(argv[i], (char*)uarg, MAXARGLEN)<0) if (argv[i]==nullptr || fetchstr(argv[i], (char*)uarg, MAXARGLEN)<0)
goto clean; goto clean;
} }
argv[i] = 0; argv[i] = 0;
r = exec(path, argv, &ascope); r = exec(path, argv, &ascope);
clean: clean:
for (i=i-i; i >= 0; i--) for (i=i-1; i >= 0; i--)
kmfree(argv[i], MAXARGLEN); kmfree(argv[i], MAXARGLEN);
return r; return r;
} }
//SYSCALL //SYSCALL
int int
sys_exec(const char *upath, userptr<userptr<const char> > uargv)
{
#if EXECSWITCH
myproc()->exec_cpuid_ = mycpuid();
myproc()->uargv = uargv;
barrier();
// upath serves as a flag to the scheduler
myproc()->upath = upath;
yield();
myproc()->upath = nullptr;
#endif
return doexec(upath, uargv);
}
//SYSCALL
int
sys_pipe(int *fd) sys_pipe(int *fd)
{ {
struct file *rf, *wf; struct file *rf, *wf;
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#define USERWQSIZE (1 << 14) #define USERWQSIZE (1 << 14)
#define USTACKPAGES 8 #define USTACKPAGES 8
#define WQSHIFT 7 #define WQSHIFT 7
#define CILKENABLE 0 #define EXECSWITCH 1
#if defined(HW_qemu) #if defined(HW_qemu)
#define NCPU 8 // maximum number of CPUs #define NCPU 8 // maximum number of CPUs
#define MTRACE 0 #define MTRACE 0
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论