Exemple #1
0
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");
}
Exemple #2
0
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;
	}
}
Exemple #3
0
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));
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
0
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);
}