void init_startup_thread(uint32_t arg) { /* Threads have arguments for functions they run, we don't need any. Silence the compiler warning by using the argument. */ arg = arg; process_id_t pid; kprintf("Mounting filesystems\n"); vfs_mount_all(); kprintf("Initializing networking\n"); network_init(); if(bootargs_get("initprog") == NULL) { kprintf("No initial program (initprog), dropping to fallback\n"); init_startup_fallback(); } kprintf("Starting initial program '%s'\n", bootargs_get("initprog")); pid = process_spawn(bootargs_get("initprog")); if (pid < 0) KERNEL_PANIC("Couldn't fit initial program in process table.\n"); process_join(pid); halt_kernel(); }
/** * Handle system calls. Interrupts are enabled when this function is * called. * * @param user_context The userland context (CPU registers as they * where when system call instruction was called in userland) */ void syscall_handle(context_t *user_context) { /* When a syscall is executed in userland, register a0 contains * the number of the syscall. Registers a1, a2 and a3 contain the * arguments of the syscall. The userland code expects that after * returning from the syscall instruction the return value of the * syscall is found in register v0. Before entering this function * the userland context has been saved to user_context and after * returning from this function the userland context will be * restored from user_context. */ switch(user_context->cpu_regs[MIPS_REGISTER_A0]) { case SYSCALL_HALT: halt_kernel(); break; case SYSCALL_READ: user_context->cpu_regs[MIPS_REGISTER_V0] = read(user_context->cpu_regs[MIPS_REGISTER_A1] ,(void*)user_context->cpu_regs[MIPS_REGISTER_A2] ,user_context->cpu_regs[MIPS_REGISTER_A3]); break; case SYSCALL_WRITE: // TODO user_context->cpu_regs[MIPS_REGISTER_V0] = write(user_context->cpu_regs[MIPS_REGISTER_A1] ,(void*)user_context->cpu_regs[MIPS_REGISTER_A2] ,user_context->cpu_regs[MIPS_REGISTER_A3]); break; default: KERNEL_PANIC("Unhandled system call\n"); } /* Move to next instruction after system call */ user_context->pc += 4; }
/** * Handle system calls. Interrupts are enabled when this function is * called. * * @param user_context The userland context (CPU registers as they * where when system call instruction was called in userland) */ void syscall_handle(context_t *user_context) { /* When a syscall is executed in userland, register a0 contains * the number of the syscall. Registers a1, a2 and a3 contain the * arguments of the syscall. The userland code expects that after * returning from the syscall instruction the return value of the * syscall is found in register v0. Before entering this function * the userland context has been saved to user_context and after * returning from this function the userland context will be * restored from user_context. */ int retval; switch(user_context->cpu_regs[MIPS_REGISTER_A0]) { case SYSCALL_HALT: halt_kernel(); break; case SYSCALL_EXEC: retval = (int) process_spawn((char*) user_context->cpu_regs[MIPS_REGISTER_A1]); user_context->cpu_regs[MIPS_REGISTER_V0] = retval; break; case SYSCALL_EXIT: /* Resources are cleaned up in process_finish(...) */ process_finish(user_context->cpu_regs[MIPS_REGISTER_A1]); break; case SYSCALL_JOIN: retval = process_join(user_context->cpu_regs[MIPS_REGISTER_A1]); user_context->cpu_regs[MIPS_REGISTER_V0] = retval; break; case SYSCALL_READ: { int fhandle = user_context->cpu_regs[MIPS_REGISTER_A1]; int buffer = user_context->cpu_regs[MIPS_REGISTER_A2]; int length = user_context->cpu_regs[MIPS_REGISTER_A3]; int retval = syscall_read(fhandle, (void *)buffer, length); user_context->cpu_regs[MIPS_REGISTER_V0] = retval; } break; case SYSCALL_WRITE: { int fhandle = user_context->cpu_regs[MIPS_REGISTER_A1]; int buffer = user_context->cpu_regs[MIPS_REGISTER_A2]; int length = user_context->cpu_regs[MIPS_REGISTER_A3]; int retval = syscall_write(fhandle, (void *)buffer, length); user_context->cpu_regs[MIPS_REGISTER_V0] = retval; } break; default: KERNEL_PANIC("Unhandled system call\n"); } /* Move to next instruction after system call */ user_context->pc += 4; }
/** * Handle system calls. Interrupts are enabled when this function is * called. * * @param user_context The userland context (CPU registers as they * where when system call instruction was called in userland) */ void syscall_handle(context_t *user_context) { int A1 = user_context->cpu_regs[MIPS_REGISTER_A1]; int A2 = user_context->cpu_regs[MIPS_REGISTER_A2]; int A3 = user_context->cpu_regs[MIPS_REGISTER_A3]; /* When a syscall is executed in userland, register a0 contains * the number of the syscall. Registers a1, a2 and a3 contain the * arguments of the syscall. The userland code expects that after * returning from the syscall instruction the return value of the * syscall is found in register v0. Before entering this function * the userland context has been saved to user_context and after * returning from this function the userland context will be * restored from user_context. */ switch(user_context->cpu_regs[MIPS_REGISTER_A0]) { case SYSCALL_HALT: halt_kernel(); break; case SYSCALL_EXIT: syscall_exit(A1); break; case SYSCALL_WRITE: user_context->cpu_regs[MIPS_REGISTER_V0] = syscall_write(A1, (char *)A2, A3); break; case SYSCALL_READ: user_context->cpu_regs[MIPS_REGISTER_V0] = syscall_read(A1, (char *)A2, A3); break; case SYSCALL_JOIN: user_context->cpu_regs[MIPS_REGISTER_V0] = syscall_join(A1); break; case SYSCALL_EXEC: user_context->cpu_regs[MIPS_REGISTER_V0] = syscall_exec((char *)A1); break; default: KERNEL_PANIC("Unhandled system call\n"); } /* Move to next instruction after system call */ user_context->pc += 4; }
/** * Handle system calls. Interrupts are enabled when this function is * called. * * @param user_context The userland context (CPU registers as they * where when system call instruction was called in userland) */ void syscall_handle(context_t *user_context) { /* When a syscall is executed in userland, register a0 contains * the number of the syscall. Registers a1, a2 and a3 contain the * arguments of the syscall. The userland code expects that after * returning from the syscall instruction the return value of the * syscall is found in register v0. Before entering this function * the userland context has been saved to user_context and after * returning from this function the userland context will be * restored from user_context. */ switch (A0) { case SYSCALL_HALT: halt_kernel(); break; case SYSCALL_READ: V0 = tty_read((int) A1, (void*) A2, (int) A3); break; case SYSCALL_WRITE: V0 = tty_write((int) A1, (void*) A2, (int) A3); break; case SYSCALL_EXEC: V0 = syscall_exec((char*) A1); break; case SYSCALL_EXIT: syscall_exit((int) A1); break; case SYSCALL_JOIN: V0 = syscall_join((process_id_t) A1); break; case SYSCALL_MEMLIMIT: V0 = (int)process_memlimit((void *) A1); break; default: KERNEL_PANIC("Unhandled system call\n"); } /* Move to next instruction after system call */ user_context->pc += 4; }
/** * Handle system calls. Interrupts are enabled when this function is * called. */ uintptr_t syscall_entry(uintptr_t syscall, uintptr_t arg0, uintptr_t arg1, uintptr_t arg2) { arg0 = arg0; arg1 = arg1; arg2 = arg2; /* When a syscall is executed in userland, register a0 contains * the number of the syscall. Registers a1, a2 and a3 contain the * arguments of the syscall. The userland code expects that after * returning from the syscall instruction the return value of the * syscall is found in register v0. Before entering this function * the userland context has been saved to user_context and after * returning from this function the userland context will be * restored from user_context. */ switch(syscall) { case SYSCALL_HALT: halt_kernel(); break; case SYSCALL_READ: return syscall_read((void*)arg1); break; case SYSCALL_WRITE: return syscall_write((const void*)arg1, (int)arg2); break; case SYSCALL_SPAWN: return syscall_spawn((char const*)arg0, (void*) arg1); break; case SYSCALL_EXIT: syscall_exit((int)arg0); break; case SYSCALL_JOIN: return process_join((int)arg0); break; default: KERNEL_PANIC("Unhandled system call\n"); } return 0; }
/** * Fallback function for system startup. This function is executed * if the initial startup program (shell or other userland process given * with initprog boot argument) is not started or specified. * * This is a good place for some kernel test code! * */ void init_startup_fallback(void) { DEBUG("debuginit", "In init_startup_fallback\n"); /* Run console test if "testconsole" was given as boot argument. */ if (bootargs_get("testconsole") != NULL) { device_t *dev; gcd_t *gcd; char buffer[64]; char buffer2[64]; int len; DEBUG("debuginit", "In console test\n"); /* Find system console (first tty) */ dev = device_get(YAMS_TYPECODE_TTY, 0); KERNEL_ASSERT(dev != NULL); gcd = (gcd_t *)dev->generic_device; KERNEL_ASSERT(gcd != NULL); len = snprintf(buffer, 63, "Hello user! Press any key.\n"); gcd->write(gcd, buffer, len); len = gcd->read(gcd, buffer2, 63); KERNEL_ASSERT(len >= 0); buffer2[len] = '\0'; len = snprintf(buffer, 63, "You said: '%s'\n", buffer2); gcd->write(gcd, buffer, len); DEBUG("debuginit", "Console test done, %d bytes written\n", len); } /* Nothing else to do, so we shut the system down. */ kprintf("Startup fallback code ends.\n"); halt_kernel(); }
/** * Hello world */ void hello_world(void) { kprintf("Hello world\n"); halt_kernel(); }
/** * Handle system calls. Interrupts are enabled when this function is * called. * * @param user_context The userland context (CPU registers as they * where when system call instruction was called in userland) */ void syscall_handle(context_t *user_context) { /* When a syscall is executed in userland, register a0 contains * the number of the syscall. Registers a1, a2 and a3 contain the * arguments of the syscall. The userland code expects that after * returning from the syscall instruction the return value of the * syscall is found in register v0. Before entering this function * the userland context has been saved to user_context and after * returning from this function the userland context will be * restored from user_context. */ switch(user_context->cpu_regs[MIPS_REGISTER_A0]) { case SYSCALL_HALT: halt_kernel(); break; case SYSCALL_EXIT: syscall_exit(user_context->cpu_regs[MIPS_REGISTER_A1]); break; case SYSCALL_WRITE: user_context->cpu_regs[MIPS_REGISTER_V0] = syscall_write(user_context->cpu_regs[MIPS_REGISTER_A1], (char*)user_context->cpu_regs[MIPS_REGISTER_A2], (user_context->cpu_regs[MIPS_REGISTER_A3])); break; case SYSCALL_READ: user_context->cpu_regs[MIPS_REGISTER_V0] = syscall_read(user_context->cpu_regs[MIPS_REGISTER_A1], (char*)user_context->cpu_regs[MIPS_REGISTER_A2], (user_context->cpu_regs[MIPS_REGISTER_A3])); break; case SYSCALL_JOIN: user_context->cpu_regs[MIPS_REGISTER_V0] = syscall_join(user_context->cpu_regs[MIPS_REGISTER_A1]); break; case SYSCALL_EXEC: user_context->cpu_regs[MIPS_REGISTER_V0] = syscall_exec((char*)user_context->cpu_regs[MIPS_REGISTER_A1]); break; case SYSCALL_FORK: user_context->cpu_regs[MIPS_REGISTER_V0] = syscall_fork((void (*)(int))user_context->cpu_regs[MIPS_REGISTER_A1], user_context->cpu_regs[MIPS_REGISTER_A2]); break; case SYSCALL_LOCK_CREATE: user_context->cpu_regs[MIPS_REGISTER_V0] = syscall_lock_create((lock_t*) user_context->cpu_regs[MIPS_REGISTER_A1]); break; case SYSCALL_LOCK_ACQUIRE: syscall_lock_acquire((lock_t*) user_context->cpu_regs[MIPS_REGISTER_A1]); break; case SYSCALL_LOCK_RELEASE: syscall_lock_release((lock_t*) user_context->cpu_regs[MIPS_REGISTER_A1]); break; case SYSCALL_CONDITION_CREATE: user_context->cpu_regs[MIPS_REGISTER_V0] = syscall_condition_create((cond_t*) user_context->cpu_regs[MIPS_REGISTER_A1]); break; case SYSCALL_CONDITION_WAIT: syscall_condition_wait((cond_t*) user_context->cpu_regs[MIPS_REGISTER_A1], (lock_t*) user_context->cpu_regs[MIPS_REGISTER_A2]); break; case SYSCALL_CONDITION_SIGNAL: syscall_condition_signal((cond_t*) user_context->cpu_regs[MIPS_REGISTER_A1], (lock_t*) user_context->cpu_regs[MIPS_REGISTER_A2]); break; case SYSCALL_CONDITION_BROADCAST: syscall_condition_broadcast((cond_t*) user_context->cpu_regs[MIPS_REGISTER_A1], (lock_t*) user_context->cpu_regs[MIPS_REGISTER_A2]); break; default: KERNEL_PANIC("Unhandled system call\n"); } /* Move to next instruction after system call */ user_context->pc += 4; }
/** * Handle system calls. Interrupts are enabled when this function is * called. * * @param user_context The userland context (CPU registers as they * where when system call instruction was called in userland) */ void syscall_handle(context_t *user_context) { /* When a syscall is executed in userland, register a0 contains * the number of the syscall. Registers a1, a2 and a3 contain the * arguments of the syscall. The userland code expects that after * returning from the syscall instruction the return value of the * syscall is found in register v0. Before entering this function * the userland context has been saved to user_context and after * returning from this function the userland context will be * restored from user_context. */ switch (A0) { case SYSCALL_HALT: halt_kernel(); break; case SYSCALL_READ: { int filehandle = (int)A1; if (filehandle == FILEHANDLE_STDIN || filehandle == FILEHANDLE_STDOUT || filehandle == FILEHANDLE_STDERR) { V0 = io_read((int) A1, (void*) A2, (int) A3); } else { V0 = syscall_read((openfile_t)A1, (void *)A2, (int)A3); } } break; case SYSCALL_WRITE: { int filehandle = (int)A1; if (filehandle == FILEHANDLE_STDIN || filehandle == FILEHANDLE_STDOUT || filehandle == FILEHANDLE_STDERR) { V0 = io_write((int) A1, (void*) A2, (int) A3); } else { V0 = syscall_write((openfile_t)A1, (void *)A2, (int)A3); } } break; case SYSCALL_EXEC: V0 = syscall_exec((char*) A1); break; case SYSCALL_EXIT: syscall_exit((int) A1); break; case SYSCALL_JOIN: V0 = syscall_join((process_id_t) A1); break; case SYSCALL_OPEN: V0 = syscall_open((char *) A1); break; case SYSCALL_CLOSE: V0 = syscall_close((openfile_t) A1); break; case SYSCALL_SEEK: V0 = syscall_seek((openfile_t)A1, (int)A2); break; case SYSCALL_CREATE: V0 = syscall_create((const char *)A1, (int)A2); break; case SYSCALL_REMOVE: V0 = syscall_remove((const char *)A1); break; case SYSCALL_TELL: V0 = syscall_tell((openfile_t)A1); break; case SYSCALL_SEM_OPEN: V0 = (uint32_t) usr_sem_open((char*) A1, A2); break; case SYSCALL_SEM_PROCURE: V0 = usr_sem_p((usr_sem_t*) A1); break; case SYSCALL_SEM_VACATE: V0 = usr_sem_v((usr_sem_t*) A1); break; case SYSCALL_SEM_DESTROY: V0 = usr_sem_destroy((usr_sem_t*) A1); break; default: KERNEL_PANIC("Unhandled system call\n"); } /* Move to next instruction after system call */ user_context->pc += 4; }