/* * Read a 256 byte (64 dword) EPROM page. * All callers have verified the offset is at a page boundary. */ static void read_page(struct hfi1_devdata *dd, u32 offset, u32 *result) { int i; write_csr(dd, ASIC_EEP_ADDR_CMD, CMD_READ_DATA(offset)); for (i = 0; i < EP_PAGE_DWORDS; i++) result[i] = (u32)read_csr(dd, ASIC_EEP_DATA); write_csr(dd, ASIC_EEP_ADDR_CMD, CMD_NOP); /* close open page */ }
void boot_loader() { extern char trap_entry; write_csr(stvec, &trap_entry); write_csr(sscratch, 0); write_csr(sie, 0); file_init(); enter_supervisor_mode(rest_of_boot_loader, pk_vm_init()); }
void boot_loader(uintptr_t dtb) { extern char trap_entry; write_csr(stvec, &trap_entry); write_csr(sscratch, 0); write_csr(sie, 0); set_csr(sstatus, SSTATUS_SUM | SSTATUS_FS); file_init(); enter_supervisor_mode(rest_of_boot_loader, pk_vm_init(), 0); }
uintptr_t mcall_set_timer(unsigned long long when) { write_csr(mtimecmp, when); clear_csr(mip, MIP_STIP); set_csr(mie, MIP_MTIP); return 0; }
void handle_misaligned_load(trapframe *tf) { printk(BIOS_DEBUG, "Trapframe ptr: %p\n", tf); uintptr_t faultingInstructionAddr = tf->epc; insn_t faultingInstruction = fetch_instruction(faultingInstructionAddr); printk(BIOS_DEBUG, "Faulting instruction: 0x%x\n", faultingInstruction); insn_t widthMask = 0x7000; insn_t memWidth = (faultingInstruction & widthMask) >> 12; insn_t destMask = 0xF80; insn_t destRegister = (faultingInstruction & destMask) >> 7; printk(BIOS_DEBUG, "Width: 0x%x\n", memWidth); if (memWidth == 3) { // load double, handle the issue void* badAddress = (void*) tf->badvaddr; uint64_t value = 0; for (int i = 0; i < 8; i++) { value <<= 8; value += mprv_read_u8(badAddress+i); } tf->gpr[destRegister] = value; } else { // panic, this should not have happened die("Code should not reach this path, misaligned on a non-64 bit store/load\n"); } // return to where we came from write_csr(mepc, read_csr(mepc) + 4); asm volatile("j machine_call_return"); }
void trap_handler(trapframe *tf) { write_csr(mscratch, tf); switch(tf->cause) { case CAUSE_MISALIGNED_FETCH: case CAUSE_FAULT_FETCH: case CAUSE_ILLEGAL_INSTRUCTION: case CAUSE_BREAKPOINT: case CAUSE_FAULT_LOAD: case CAUSE_FAULT_STORE: case CAUSE_USER_ECALL: case CAUSE_HYPERVISOR_ECALL: case CAUSE_MACHINE_ECALL: print_trap_information(tf); break; case CAUSE_MISALIGNED_LOAD: print_trap_information(tf); handle_misaligned_load(tf); break; case CAUSE_MISALIGNED_STORE: print_trap_information(tf); handle_misaligned_store(tf); break; case CAUSE_SUPERVISOR_ECALL: /* Don't print so we make console putchar calls look the way they should */ handle_supervisor_call(tf); break; default: print_trap_information(tf); break; } die("Can't recover from trap. Halting.\n"); }
void _init() { #ifndef NO_INIT use_default_clocks(); use_pll(0, 0, 1, 31, 1); uart_init(115200); rt_kprintf("core freq at %ld Hz\n", get_cpu_freq()); write_csr(mtvec, &trap_entry); if (read_csr(misa) & (1 << ('F' - 'A'))) { // if F extension is present write_csr(mstatus, MSTATUS_FS); // allow FPU instructions without trapping write_csr(fcsr, 0); // initialize rounding mode, undefined at reset } #endif }
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"); }
uintptr_t mcall_send_ipi(uintptr_t recipient) { //if (recipient >= num_harts) //return -1; if (atomic_swap(&OTHER_HLS(recipient)->ipi_pending, 1) == 0) { mb(); write_csr(send_ipi, recipient); } return 0; }
static void mstatus_init() { if (!supports_extension('S')) panic("supervisor support is required"); uintptr_t ms = 0; ms = INSERT_FIELD(ms, MSTATUS_PRV, PRV_M); ms = INSERT_FIELD(ms, MSTATUS_PRV1, PRV_S); ms = INSERT_FIELD(ms, MSTATUS_PRV2, PRV_U); ms = INSERT_FIELD(ms, MSTATUS_IE2, 1); ms = INSERT_FIELD(ms, MSTATUS_VM, VM_CHOICE); ms = INSERT_FIELD(ms, MSTATUS_FS, 3); ms = INSERT_FIELD(ms, MSTATUS_XS, 3); write_csr(mstatus, ms); ms = read_csr(mstatus); if (EXTRACT_FIELD(ms, MSTATUS_VM) != VM_CHOICE) have_vm = 0; write_csr(mtimecmp, 0); clear_csr(mip, MIP_MSIP); set_csr(mie, MIP_MSIP); }
/* * Initialize the EPROM handler. */ int eprom_init(struct hfi1_devdata *dd) { int ret = 0; /* only the discrete chip has an EPROM */ if (dd->pcidev->device != PCI_DEVICE_ID_INTEL0) return 0; /* * It is OK if both HFIs reset the EPROM as long as they don't * do it at the same time. */ ret = acquire_chip_resource(dd, CR_EPROM, EPROM_TIMEOUT); if (ret) { dd_dev_err(dd, "%s: unable to acquire EPROM resource, no EPROM support\n", __func__); goto done_asic; } /* reset EPROM to be sure it is in a good state */ /* set reset */ write_csr(dd, ASIC_EEP_CTL_STAT, ASIC_EEP_CTL_STAT_EP_RESET_SMASK); /* clear reset, set speed */ write_csr(dd, ASIC_EEP_CTL_STAT, EP_SPEED_FULL << ASIC_EEP_CTL_STAT_RATE_SPI_SHIFT); /* wake the device with command "release powerdown NoID" */ write_csr(dd, ASIC_EEP_ADDR_CMD, CMD_RELEASE_POWERDOWN_NOID); dd->eprom_available = true; release_chip_resource(dd, CR_EPROM); done_asic: return ret; }
uintptr_t mcall_console_putchar(uint8_t ch) { while (swap_csr(mtohost, TOHOST_CMD(1, 1, ch)) != 0); while (1) { uintptr_t fromhost = read_csr(mfromhost); if (FROMHOST_DEV(fromhost) != 1 || FROMHOST_CMD(fromhost) != 1) { if (fromhost) htif_interrupt(0, 0); continue; } write_csr(mfromhost, 0); break; } return 0; }
static void fp_init() { kassert(read_csr(mstatus) & MSTATUS_FS); #ifdef __riscv_hard_float if (!supports_extension('D')) panic("FPU not found; recompile pk with -msoft-float"); for (int i = 0; i < 32; i++) init_fp_reg(i); write_csr(fcsr, 0); #else if (supports_extension('D')) panic("FPU unexpectedly found; recompile pk without -msoft-float"); #endif }
static void init_other_hart() { // wait until virtual memory is enabled while (root_page_table == NULL) asm volatile ("" ::: "memory"); mb(); write_csr(sptbr, root_page_table); // then make sure we're in bounds if (HLS()->hart_id >= num_harts) { while (1) wfi(); } boot_other_hart(); }
static void enter_entry_point() { write_csr(mepc, current.entry); asm volatile("eret"); __builtin_unreachable(); }
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); }
uintptr_t mcall_shutdown(void) { while (1) write_csr(mtohost, 1); return 0; }