$ git checkout lab1_challenge3_multicore $ git merge lab1_3_irq -m "continue to work on lab1_challenge3" $ make clean;make $ spike -p2 ./obj/riscv-pke ./obj/app0 ./obj/app1
输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
HTIF is available! (Emulated) memory size: 2048 MB In m_start, hartid:0 hartid = 0: Enter supervisor mode... hartid = 0: Application: ./obj/app0 hartid = 0: Application program entry point (virtual address): 0x0000000081000000 hartid = 0: Switch to user mode... In m_start, hartid:1 hartid = 1: Enter supervisor mode... hartid = 1: Application: ./obj/app1 hartid = 1: Application program entry point (virtual address): 0x0000000085000000 hartid = 1: Switch to user mode... hartid = 0: >>> app0 is expected to be executed by hart0 hartid = 1: >>> app1 is expected to be executed by hart1 hartid = 0: User exit with code:0. hartid = 1: User exit with code:0. hartid = 0: shutdown with code:0. System is shutting down with exit code 0.
// // m_start: machine mode C entry point. // int counter = 0; voidm_start(uintptr_t hartid, uintptr_t dtb) { // only cpu0 (hartid == 0) will init if (hartid == 0) { // init the spike file interface (stdin,stdout,stderr) // functions with "spike_" prefix are all defined in codes under spike_interface/, // sprint is also defined in spike_interface/spike_utils.c spike_file_init(); // init HTIF and memory by using the Device Table Blob (DTB) // init_dtb() is defined above. init_dtb(dtb); } sync_barrier(&counter, NCPU); sprint("In m_start, hartid:%d\n", hartid);
// global variable that store the recorded "ticks". added @lab1_3 static uint64 g_ticks[NCPU] = {0}; // voidhandle_mtimer_trap() { sprint("Ticks %d\n", g_ticks); // TODO (lab1_3): increase g_ticks to record this "tick", and then clear the "SIP" // field in sip register. // hint: use write_csr to disable the SIP_SSIP bit in sip. g_ticks[read_tp()]++; write_csr(sip, !SIP_SSIP); } // kernel/smode_trap.S will pass control to smode_trap_handler, when a trap happens // in S-mode. // voidsmode_trap_handler(void) { ...
assert(read_tp() < NCPU); process *p = &apps[read_tp()]; // save user process counter. p->trapframe->epc = read_csr(sepc);
...
// continue (come back to) the execution of current process. switch_to(p); }
// current points to the currently running user-mode application. process* current = NULL; // // switch to a user-mode process // voidswitch_to(process* proc) { assert(proc); current = proc; ... }
改为
1 2 3 4 5 6 7 8 9 10 11
// processes that are running on each CPU process apps[NCPU]; // // switch to a user-mode process // voidswitch_to(process* proc) { assert(proc); ... proc->trapframe->hartid = read_tp(); ... }
/* we use fixed physical (also logical) addresses for the stacks and trap frames as in Bare memory-mapping mode */ // user stack top #define USER_STACK (0x81100000 + (uint64)read_tp() * 0x4000000)
// the stack used by PKE kernel when a syscall happens #define USER_KSTACK (0x81200000 + (uint64)read_tp() * 0x4000000)
// the trap frame used to assemble the user "process" #define USER_TRAP_FRAME (0x81300000 + (uint64)read_tp() * 0x4000000)
#endif
5.elf.c修改,让pke能从命令行加载第二个app。
1 2 3 4 5 6 7 8 9 10 11 12 13
// // load the elf of user application, by using the spike file interface. // voidload_bincode_from_host_elf(process *p) { // added int hartid = read_tp(); ... sprint("hartid = %d: Application: %s\n", hartid, arg_bug_msg.argv[hartid]); ... info.f = spike_file_open(arg_bug_msg.argv[hartid], O_RDONLY, 0); ... sprint("hartid = %d: Application program entry point (virtual address): 0x%lx\n", hartid, p->trapframe->epc); }
int exit_counter = 0; // // implement the SYS_user_exit syscall // ssize_tsys_user_exit(uint64 code) { int hartid = read_tp(); sprint("hartid = %d: User exit with code:%d.\n", hartid, code); // in lab1, PKE considers only one app (one process). // therefore, shutdown the system when the app calls exit() sync_barrier(&exit_counter, NCPU); if (hartid == 0) { sprint("hartid = %d: shutdown with code:%d.\n", hartid, code); shutdown(code); } while (1); return0; }