void handle_supervisor_call(trapframe *tf) { uintptr_t call = tf->gpr[17]; /* a7 */ uintptr_t arg0 = tf->gpr[10]; /* a0 */ uintptr_t arg1 = tf->gpr[11]; /* a1 */ uintptr_t returnValue; switch(call) { case SBI_ECALL_HART_ID: printk(BIOS_DEBUG, "Getting hart id...\n"); returnValue = read_csr(mhartid); break; case SBI_ECALL_NUM_HARTS: /* TODO: parse the hardware-supplied config string and return the correct value */ returnValue = 1; break; case SBI_ECALL_CONSOLE_PUT: returnValue = mcall_console_putchar(arg0); break; case SBI_ECALL_SEND_DEVICE_REQUEST: printk(BIOS_DEBUG, "Sending device request...\n"); returnValue = mcall_dev_req((sbi_device_message*) arg0); break; case SBI_ECALL_RECEIVE_DEVICE_RESPONSE: printk(BIOS_DEBUG, "Getting device response...\n"); returnValue = mcall_dev_resp(); break; case SBI_ECALL_SEND_IPI: printk(BIOS_DEBUG, "Sending IPI...\n"); returnValue = mcall_send_ipi(arg0); break; case SBI_ECALL_CLEAR_IPI: printk(BIOS_DEBUG, "Clearing IPI...\n"); returnValue = mcall_clear_ipi(); break; case SBI_ECALL_SHUTDOWN: printk(BIOS_DEBUG, "Shutting down...\n"); returnValue = mcall_shutdown(); break; case SBI_ECALL_SET_TIMER: printk(BIOS_DEBUG, "Setting timer to %p (current time is %p)...\n", (void *)arg0, (void *)rdtime()); returnValue = mcall_set_timer(arg0); break; case SBI_ECALL_QUERY_MEMORY: printk(BIOS_DEBUG, "Querying memory, CPU #%lld...\n", arg0); returnValue = mcall_query_memory(arg0, (memory_block_info*) arg1); break; default: printk(BIOS_DEBUG, "ERROR! Unrecognized system call\n"); returnValue = 0; break; // note: system call we do not know how to handle } tf->gpr[10] = returnValue; write_csr(mepc, read_csr(mepc) + 4); asm volatile("j supervisor_call_return"); }
arg_t _time(void) { time_t t; switch (type) { case 0: rdtime(&t); uput(&t, tvec, sizeof(t)); return (0); case 1: uput(&t.low, &ticks.full, sizeof(ticks)); uzero(&t.high, sizeof(t.high)); return 0; default: udata.u_error = EINVAL; return -1; } }
arg_t _time(void) { time_t t; switch (type) { case 0: rdtime(&t); break; case 1: t.low = ticks.full; t.high = 0; break; default: udata.u_error = EINVAL; return -1; } return uput(&t, tvec, sizeof(t)); }
fsptr getdev(uint16_t dev) { struct mount *mnt; fsptr devfs; time_t t; mnt = fs_tab_get(dev); if (!mnt || !(devfs = mnt->m_fs) || devfs->s_mounted) { panic("getdev: bad dev"); /* Return needed to persuade SDCC all is ok */ return NULL; } rdtime(&t); devfs->s_time = (uint32_t)t; devfs->s_timeh = (uint8_t)(t >> 32); devfs->s_fmod = true; ((bufptr)devfs)->bf_dirty = true; return devfs; }
arg_t _utime(void) { inoptr ino; time_t t[2]; if (!(ino = n_open(file, NULLINOPTR))) return (-1); if (ino->c_flags & CRDONLY) { udata.u_error = EROFS; goto out2; } /* Special case in the Unix API - NULL means now */ if (buf) { if (ino->c_node.i_uid != udata.u_euid && esuper()) goto out; if (!valaddr(buf, 2 * sizeof(time_t))) goto out2; uget(buf, t, 2 * sizeof(time_t)); } else { if (!(getperm(ino) & OTH_WR)) goto out; rdtime(&t[0]); memcpy(&t[1], &t[0], sizeof(t[1])); } /* FIXME: needs updating once we pack top bits elsewhere in the inode */ ino->c_node.i_atime = t[0].low; ino->c_node.i_mtime = t[1].low; setftime(ino, C_TIME); i_deref(ino); return (0); out: udata.u_error = EPERM; out2: i_deref(ino); return -1; }
static void run_loaded_program(size_t argc, char** argv, uintptr_t kstack_top) { // copy phdrs to user stack size_t stack_top = current.stack_top - current.phdr_size; memcpy((void*)stack_top, (void*)current.phdr, current.phdr_size); current.phdr = stack_top; // copy argv to user stack for (size_t i = 0; i < argc; i++) { size_t len = strlen((char*)(uintptr_t)argv[i])+1; stack_top -= len; memcpy((void*)stack_top, (void*)(uintptr_t)argv[i], len); argv[i] = (void*)stack_top; } // copy envp to user stack const char* envp[] = { // environment goes here }; size_t envc = sizeof(envp) / sizeof(envp[0]); for (size_t i = 0; i < envc; i++) { size_t len = strlen(envp[i]) + 1; stack_top -= len; memcpy((void*)stack_top, envp[i], len); envp[i] = (void*)stack_top; } // align stack stack_top &= -sizeof(void*); struct { long key; long value; } aux[] = { {AT_ENTRY, current.entry}, {AT_PHNUM, current.phnum}, {AT_PHENT, current.phent}, {AT_PHDR, current.phdr}, {AT_PAGESZ, RISCV_PGSIZE}, {AT_SECURE, 0}, {AT_RANDOM, stack_top}, {AT_NULL, 0} }; // place argc, argv, envp, auxp on stack #define PUSH_ARG(type, value) do { \ *((type*)sp) = (type)value; \ sp += sizeof(type); \ } while (0) #define STACK_INIT(type) do { \ unsigned naux = sizeof(aux)/sizeof(aux[0]); \ stack_top -= (1 + argc + 1 + envc + 1 + 2*naux) * sizeof(type); \ stack_top &= -16; \ long sp = stack_top; \ PUSH_ARG(type, argc); \ for (unsigned i = 0; i < argc; i++) \ PUSH_ARG(type, argv[i]); \ PUSH_ARG(type, 0); /* argv[argc] = NULL */ \ for (unsigned i = 0; i < envc; i++) \ PUSH_ARG(type, envp[i]); \ PUSH_ARG(type, 0); /* envp[envc] = NULL */ \ for (unsigned i = 0; i < naux; i++) { \ PUSH_ARG(type, aux[i].key); \ PUSH_ARG(type, aux[i].value); \ } \ } while (0) STACK_INIT(uintptr_t); if (current.cycle0) { // start timer if so requested current.time0 = rdtime(); current.cycle0 = rdcycle(); current.instret0 = rdinstret(); } trapframe_t tf; init_tf(&tf, current.entry, stack_top); __clear_cache(0, 0); write_csr(sscratch, kstack_top); start_user(&tf); }