Add argument passing
This commit is contained in:
parent
e261ccdcec
commit
2718379e6d
@ -78,7 +78,8 @@ Cmd_Run(int argc, const char *argv[])
|
||||
continue;
|
||||
}
|
||||
|
||||
status = OSSpawn(path);
|
||||
argv[argc] = NULL;
|
||||
status = OSSpawn(path, &argv[0]);
|
||||
if (status > 100000) {
|
||||
printf("Spawn failed!\n");
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
uint64_t OSTime();
|
||||
uint64_t OSGetPID();
|
||||
void OSExit(int status);
|
||||
uint64_t OSSpawn(const char *path);
|
||||
uint64_t OSSpawn(const char *path, const char *argv[]);
|
||||
uint64_t OSWait(uint64_t pid);
|
||||
|
||||
// Memory
|
||||
|
@ -105,8 +105,8 @@ _start(char **ap)
|
||||
char **argv = NULL;
|
||||
char **env = NULL;
|
||||
|
||||
//argc = *(long *)(void *)ap;
|
||||
//argv = ap + 1;
|
||||
argc = *(long *)(void *)ap;
|
||||
argv = ap + 1;
|
||||
//env = ap + 2 + argc;
|
||||
handle_argv(argc, argv, env);
|
||||
|
||||
|
@ -26,9 +26,9 @@ OSGetPID()
|
||||
}
|
||||
|
||||
uint64_t
|
||||
OSSpawn(const char *path)
|
||||
OSSpawn(const char *path, const char *argv[])
|
||||
{
|
||||
return syscall(SYSCALL_SPAWN, path);
|
||||
return syscall(SYSCALL_SPAWN, path, argv);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
@ -97,6 +97,12 @@ OSReadDir(uint64_t fd, char *buf, size_t length, uint64_t *offset)
|
||||
return syscall(SYSCALL_READDIR, fd, buf, length, offset);
|
||||
}
|
||||
|
||||
int
|
||||
OSPipe(uint64_t fd[2])
|
||||
{
|
||||
return syscall(SYSCALL_PIPE, &fd[0]);
|
||||
}
|
||||
|
||||
int
|
||||
OSThreadCreate(uint64_t rip, uint64_t arg)
|
||||
{
|
||||
|
@ -15,7 +15,7 @@ src.append(src_common)
|
||||
src.append(env["CRTEND"])
|
||||
|
||||
init_env.Append(LINKFLAGS = ['-nostdlib'])
|
||||
init_env.Append(CPPFLAGS = ['-nostdinc'])
|
||||
init_env.Append(CPPFLAGS = ['-nostdinc', '-mno-sse'])
|
||||
init_env.Append(CPPPATH = ['#build/include'])
|
||||
init_env.Append(LIBPATH = ['#build/lib/libc'], LIBS = ['c'])
|
||||
|
||||
|
@ -8,7 +8,8 @@ main(int argc, const char *argv[])
|
||||
|
||||
fputs("Init spawning shell\n", stdout);
|
||||
|
||||
status = OSSpawn("/bin/shell");
|
||||
const char *args[] = { "/bin/shell", NULL };
|
||||
status = OSSpawn("/bin/shell", &args[0]);
|
||||
if (status > 100) {
|
||||
printf("init: Could not spawn shell %016lx\n", status);
|
||||
}
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
#define MEM_USERSPACE_STKBASE 0x0000000070000000ULL
|
||||
#define MEM_USERSPACE_STKLEN 0x0000000000010000ULL
|
||||
#define MEM_USERSPACE_STKTOP (MEM_USERSPACE_STKBASE + MEM_USERSPACE_STKLEN)
|
||||
|
||||
#define MEM_DIRECTMAP_BASE 0xFFFF800000000000ULL
|
||||
#define MEM_DIRECTMAP_LEN 0x0000010000000000ULL
|
||||
|
@ -63,7 +63,7 @@ ThreadEnterUserLevelCB(uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
|
||||
tf.ds = SEL_UDS | 3;
|
||||
tf.rip = (uint64_t)arg1;
|
||||
tf.cs = SEL_UCS | 3;
|
||||
tf.rsp = (uint64_t)arg2 + MEM_USERSPACE_STKLEN;
|
||||
tf.rsp = (uint64_t)arg2 + MEM_USERSPACE_STKLEN - PGSIZE;
|
||||
tf.ss = SEL_UDS | 3;
|
||||
tf.rflags = RFLAGS_IF;
|
||||
tf.rdi = (uint64_t)arg3; /* Userspace Argument */
|
||||
@ -83,6 +83,10 @@ extern TaskStateSegment64 TSS[MAX_CPUS];
|
||||
void
|
||||
Thread_SwitchArch(Thread *oldthr, Thread *newthr)
|
||||
{
|
||||
/*
|
||||
* Save and restore floating point and vector CPU state using the fxsave
|
||||
* and fxrstor instructions.
|
||||
*/
|
||||
if (oldthr->arch.useFP)
|
||||
{
|
||||
fxsave(&oldthr->arch.xsa);
|
||||
|
@ -98,15 +98,23 @@ Loader_LoadFirst(Thread *thr, VNode *vn, void *buf, uint64_t len)
|
||||
|
||||
Log(loader, "Jumping to userspace\n");
|
||||
|
||||
uintptr_t ap[3];
|
||||
ap[0] = 0;
|
||||
ap[1] = 0;
|
||||
ap[2] = 0xDEADBEEF;
|
||||
uintptr_t rsp = MEM_USERSPACE_STKTOP - PGSIZE;
|
||||
|
||||
Copy_Out(&ap[0], rsp, sizeof(uintptr_t)*3);
|
||||
|
||||
TrapFrame tf;
|
||||
memset(&tf, 0, sizeof(tf));
|
||||
tf.ds = SEL_UDS | 3;
|
||||
tf.rip = ehdr->e_entry;
|
||||
tf.cs = SEL_UCS | 3;
|
||||
tf.rsp = MEM_USERSPACE_STKBASE + MEM_USERSPACE_STKLEN;
|
||||
tf.rsp = rsp;
|
||||
tf.ss = SEL_UDS | 3;
|
||||
tf.rflags = RFLAGS_IF;
|
||||
tf.rdi = 0;
|
||||
tf.rdi = rsp;
|
||||
Trap_Pop(&tf);
|
||||
|
||||
return true;
|
||||
@ -262,7 +270,7 @@ Loader_Load(Thread *thr, VNode *vn, void *buf, uint64_t len)
|
||||
}
|
||||
}
|
||||
|
||||
Thread_SetupUThread(thr, ehdr->e_entry, 0);
|
||||
Thread_SetupUThread(thr, ehdr->e_entry, MEM_USERSPACE_STKTOP - PGSIZE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -61,11 +61,12 @@ Syscall_Exit(uint64_t status)
|
||||
}
|
||||
|
||||
uint64_t
|
||||
Syscall_Spawn(uint64_t user_path)
|
||||
Syscall_Spawn(uint64_t user_path, uint64_t user_argv)
|
||||
{
|
||||
int status;
|
||||
char path[512];
|
||||
void *pg;
|
||||
char *arg;
|
||||
VNode *file;
|
||||
Process *proc;
|
||||
Thread *thr;
|
||||
@ -77,14 +78,52 @@ Syscall_Spawn(uint64_t user_path)
|
||||
|
||||
Log(syscall, "Spawn(%s)\n", path);
|
||||
|
||||
arg = PAlloc_AllocPage();
|
||||
if (!arg) {
|
||||
return SYSCALL_PACK(ENOMEM, 0);
|
||||
}
|
||||
|
||||
/* Copy argument pointers */
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uintptr_t off = sizeof(uintptr_t)*i;
|
||||
|
||||
status = Copy_In(user_argv+off, arg+sizeof(uintptr_t)*(1+i), sizeof(uintptr_t));
|
||||
if (status != 0) {
|
||||
PAlloc_Release(arg);
|
||||
return SYSCALL_PACK(status, 0);
|
||||
}
|
||||
|
||||
if (*(uintptr_t *)(arg+sizeof(uintptr_t)*(1+i)) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy each argument in */
|
||||
char *argstart = arg+sizeof(uintptr_t)*1;
|
||||
for (int i = 3; i < 8; i++) {
|
||||
uintptr_t *str = (uintptr_t *)(arg+sizeof(uintptr_t)*i);
|
||||
if (*str == 0)
|
||||
break;
|
||||
|
||||
status = Copy_StrIn(*str, argstart, 256); // XXX: Make sure there's no overrun
|
||||
if (status != 0) {
|
||||
PAlloc_Release(arg);
|
||||
return SYSCALL_PACK(status, 0);
|
||||
}
|
||||
|
||||
*str = (uintptr_t)argstart;
|
||||
argstart += strlen(argstart)+1;
|
||||
}
|
||||
|
||||
pg = PAlloc_AllocPage();
|
||||
if (!pg) {
|
||||
PAlloc_Release(arg);
|
||||
return SYSCALL_PACK(ENOMEM, 0);
|
||||
}
|
||||
|
||||
file = VFS_Lookup(path);
|
||||
if (!file) {
|
||||
// Free
|
||||
PAlloc_Release(pg);
|
||||
PAlloc_Release(arg);
|
||||
return SYSCALL_PACK(ENOENT, 0);
|
||||
}
|
||||
|
||||
@ -92,6 +131,8 @@ Syscall_Spawn(uint64_t user_path)
|
||||
if (status < 0) {
|
||||
Log(syscall, "Error VFS_Open\n");
|
||||
// Release & free
|
||||
PAlloc_Release(pg);
|
||||
PAlloc_Release(arg);
|
||||
return SYSCALL_PACK(status, 0);
|
||||
}
|
||||
|
||||
@ -99,10 +140,16 @@ Syscall_Spawn(uint64_t user_path)
|
||||
if (status < 0) {
|
||||
Log(syscall, "Error VFS_Read\n");
|
||||
// Release & free
|
||||
VFS_Close(file);
|
||||
PAlloc_Release(pg);
|
||||
PAlloc_Release(arg);
|
||||
return SYSCALL_PACK(status, 0);
|
||||
}
|
||||
|
||||
if (!Loader_CheckHeader(pg)) {
|
||||
VFS_Close(file);
|
||||
PAlloc_Release(pg);
|
||||
PAlloc_Release(arg);
|
||||
return SYSCALL_PACK(EINVAL, 0);
|
||||
}
|
||||
|
||||
@ -121,6 +168,34 @@ Syscall_Spawn(uint64_t user_path)
|
||||
|
||||
Loader_Load(thr, file, pg, 1024);
|
||||
|
||||
/* Translate mapping for stack page */
|
||||
argstart = (char *)DMPA2VA(PMap_Translate(thr->space, MEM_USERSPACE_STKTOP-PGSIZE));
|
||||
argstart += sizeof(uintptr_t)*8;
|
||||
uintptr_t offset = sizeof(uintptr_t)*8;
|
||||
|
||||
/* Copy each argument and update the pointer array */
|
||||
uintptr_t *arg_ap = (uintptr_t *)arg;
|
||||
for (int i = 1; i < 8; i++) {
|
||||
uintptr_t *str = (uintptr_t *)(arg+sizeof(uintptr_t)*i);
|
||||
if (*str == 0) {
|
||||
arg_ap[0] = i - 1;
|
||||
arg_ap[i] = 0; // XXX: Environment
|
||||
break;
|
||||
}
|
||||
|
||||
size_t len = strlen((char *)arg_ap[i])+1;
|
||||
|
||||
strcpy(argstart, (char *)arg_ap[i]);
|
||||
|
||||
arg_ap[i] = (uintptr_t)(MEM_USERSPACE_STKTOP - PGSIZE + offset);
|
||||
offset += len;
|
||||
argstart += len;
|
||||
}
|
||||
|
||||
/* Copy the argument pointer array */
|
||||
argstart = (char *)DMPA2VA(PMap_Translate(thr->space, MEM_USERSPACE_STKTOP-PGSIZE));
|
||||
memcpy(argstart, arg, sizeof(uintptr_t)*8);
|
||||
|
||||
VFS_Close(file);
|
||||
|
||||
Sched_SetRunnable(thr);
|
||||
@ -651,7 +726,7 @@ Syscall_Entry(uint64_t syscall, uint64_t a1, uint64_t a2,
|
||||
Syscall_Exit(a1);
|
||||
return 0; // To eliminate warning
|
||||
case SYSCALL_SPAWN:
|
||||
return Syscall_Spawn(a1);
|
||||
return Syscall_Spawn(a1, a2);
|
||||
case SYSCALL_WAIT:
|
||||
return Syscall_Wait(a1);
|
||||
case SYSCALL_MMAP:
|
||||
|
@ -588,15 +588,10 @@ Thread_Dump(Thread *thr)
|
||||
static void
|
||||
Debug_Threads(int argc, const char *argv[])
|
||||
{
|
||||
int c = CPU();
|
||||
Thread *thr;
|
||||
|
||||
//Spinlock_Lock(&threadLock);
|
||||
|
||||
kprintf("CPU %d\n", c);
|
||||
kprintf("Current Thread: %d(%016llx) %d\n",
|
||||
curProc[c]->tid, curProc[c], curProc[c]->ctxSwitches);
|
||||
Thread_Dump(curProc[c]);
|
||||
TAILQ_FOREACH(thr, &runnableQueue, schedQueue)
|
||||
{
|
||||
kprintf("Runnable Thread: %d(%016llx) %d\n", thr->tid, thr, thr->ctxSwitches);
|
||||
@ -634,7 +629,22 @@ REGISTER_DBGCMD(processes, "Display list of processes", Debug_Processes);
|
||||
static void
|
||||
Debug_ThreadInfo(int argc, const char *argv[])
|
||||
{
|
||||
Thread *thr = curProc[CPU()];
|
||||
|
||||
kprintf("Current Thread State:\n");
|
||||
Thread_Dump(thr);
|
||||
}
|
||||
|
||||
REGISTER_DBGCMD(threadinfo, "Display thread state", Debug_ThreadInfo);
|
||||
REGISTER_DBGCMD(threadinfo, "Display current thread state", Debug_ThreadInfo);
|
||||
|
||||
static void
|
||||
Debug_ProcInfo(int argc, const char *argv[])
|
||||
{
|
||||
Thread *thr = curProc[CPU()];
|
||||
|
||||
kprintf("Current Process State:\n");
|
||||
Process_Dump(thr->proc);
|
||||
}
|
||||
|
||||
REGISTER_DBGCMD(procinfo, "Display current process state", Debug_ProcInfo);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user