### Premise * virtual page 連續不一定會在 physical frame 連續,因為跨 pages 沒有規則。 * flow: * user program link start.S 使得libaray可以找到對應的assembly * OneInstruction跑到OP_SYSCALL的時候會raise syscall exception ### Problems #### AddrSpace::Load 裡面的 load segment 需要分段存取 * 這裡他想說的是原本的readAt是直接連續phy addr去做read 但實際是virtual -> phy 時候不會在連續的phy pages裡 * 解決方案: 針對一個一個page的vaddr做(AddrSpace::Translate)取到正確的paddr ```cpp= for (int addrOffset = 0; addrOffset < noffH.code.size; addrOffset += PageSize - offset) { vaddr = noffH.code.virtualAddr + addrOffset; vpn = vaddr / PageSize; offset = vaddr % PageSize; faddr = noffH.code.inFileAddr + addrOffset; size = min(PageSize - offset, noffH.code.size - addrOffset); ExceptionType exp = Translate(vaddr, &physicalAddr, 0); if (exp == NoException) { executable->ReadAt(&(kernel->machine->mainMemory[physicalAddr]), size, faddr); pageTable[vpn].readOnly = TRUE; } else { ExceptionHandler(exp); } } ``` #### MSG、SC_Open 等涉及「char*」參數的 system call ![](https://hackmd.io/_uploads/Hyo1tcpZp.png) * However, NachOS會把 filename之類的Addr放到r4,進而導致我們read phy page時因為不連續而出錯 * function call abi #### ```cpp= case SC_MSG: DEBUG(dbgSys, "Message received.\n"); val = kernel->machine->ReadRegister(4); { char *msg = &(kernel->machine->mainMemory[val]); cout << msg << endl; } SysHalt(); ASSERTNOTREACHED(); break; ``` ### BOUNS #### Q1 * 多個PAGE為何不行 #### Q2 * 那麼現今的SYSTEM怎麼處理的? ### question 1. spec上的修改檔案是提供各位同學參考的,可以修改除了spec提到的File以外的File 2. 在理想上應該呼叫 RaiseException, 再由 RaiseException 呼叫 ExceptionHandler, 但是為了實作的便利性, 所以在這裡呼叫 ExceptionHandler 也不會有影響, 而關於 kernel 本身發生 exception 的情況 ,就我們所知 NachOS 並未去 handle 這樣的情形. 3. 如果實作完跟之前uniprogramming paradigm的實作有差異,就在Report裡面解釋不同之處即可 4. NachOS simulate MIPS 在 user-level的programs,但kernel level的operation還是執行在實際的cpu上。這也是為何需要操作real CPU's register。 5. 如果同學只是想驗證自己的實作是否能support不連續的Frame,可以通過修改kernel中phy page的順序來進行驗證。