In addition to the lectures, please use the following resources to help you with this lab:
RISC-V has functionality for "privilege modes". Depending on the privilege mode a program is in, certain functionalities or memory addresses can be enabled or disabled. This is a summary of the privilege modes:
- Machine-mode: Highest privilege, all memory addresses are enabled. Used by bootloader.
- Supervisor-mode: All addresses except user addresses are enabled. Used by OS.
- User-mode: Lowest privilege, only user addresses can be accessed. Used by programs.
A core will always start in M-mode, which does not support virtual memory. To enable virtual memory, OS must lower the privilege to either S-mode or U-mode. This is demonstrated in "programs/vm/os.S"
and "programs/vm/privilege.S"
.
You have been provided a simple Bootloader and OS: "programs/vm/os.S"
. It is an example of how to set up and enable a page table, and lower the privilege to U-mode.
These are the steps it takes in more detail:
- Run bootloader in M-mode
- Set up the page table
- Configure PMP
- Jump to the OS in S-mode
- Enable virtual memory using the page table
- Add the user program to the page table
- Load the user program to user memory
- Jump to the program in U-mode
"rvfi_tracer.sv"
hits a breakpoint atecall
and exits the simulation
Note, out of simplicity's sake, there are a few important OS features that have not been fully implemented, such as:
- The code does not implement trap handlers for
ecall
instructions. - The kernel and each user process should have their own page table.
- User processes are usually loaded to addresses starting at 0x0.
In this lab, you will be implementing basic trap handlers.
You will need the RISC-V Privileged Architecture Manual to answer some of these questions.
- What is the purpose of virtual memory?
- Define the following: MMU, PTW, TLB.
- What is the benefit of a multi-layer page table?
- For Sv39, give
- The number of bits in a VA
- The number of bits in a PA
- The number of layers a PT can be
- The size of a page in bytes
- The size of a PTE in bytes
- Complete the following page table entry questions.
- Provide a diagram of a Sv39 PTE.
- List and define the 10 bottom bits of a Sv39 page table entry.
- In
"programs/vm/os.S"
, each PTE's bottom 8 bits are set to either0x1
,0xef
, or0xff
; explain the purposes of each of these three values in the context of"programs/vm/os.S"
.
- Draw a diagram of the hierarchical page table created in
"programs/vm/os.S"
(unmodified).- Show/describe the contents of every valid PTE in each PT.
- Denote pointers from a PTE to another layer with an arrow to the corresponding PT.
- Show the contents of every valid physical frame in physical memory.
- In
"programs/vm/os.S"
and"programs/vm/privilege.S"
, several control/status registers are written. For each of the registers, provide a screenshot of the bit diagram, and a definition of each of any fields that the provided programs use. (For example,"programs/vm/os.S"
only uses theSUM
fromsstatus
, soSUM
is the only field you need to give a definition of forsstatus
).mstatus
sstatus
mepc
sepc
mtvec
stvec
satp
medeleg
The current simulation runs just one user process, then stops the simulation once the ecall
is run in the user program. However, we want to modify it to run 2 user processes sequentially, then stop the simulation if an ecall
is run in M-mode. To achieve this, we need to modify the CVA6 testbench, and modify the provided OS code.
The CVA6 testbench is currently configured that any ecall
instruction will stop the simulation. Edit this in "rvfi_tracer.sv"
so that it only exits the simulation on an ecall
in M-mode. (Hint: "rvfi_pkg.sv"
, "riscv_pkg.sv"
)
- Same initial setup...
- Create
m_trap
ands_trap
trap handlers that are assigned tomtvec
andstvec
- Set
medeleg
- Create a counter that specifies which user program should be run (initialized to 1)
- Load user program 1 to memory and configure the page table accordingly
- Run user program 1 that has an
ecall
instruction - Return to the
s_trap
trap handler - Have
s_trap
increment the user program counter, then jump back to the OS - Load user program 2 to a different VA and PA than user program 1, and configure the page table accordingly
- Run user program 2 that has an
ecall
instruction - Return to the
s_trap
trap handler - Have
s_trap
increment the user program counter, then jump back to the OS - On user program counter > 2, the OS runs
ecall
- Return to the
m_trap
trap handler - Have
m_trap
runecall
to exit the simulation
Note: reference "programs/vm/privilege.S"
to help you set up your trap handlers.
CVA6 simulations create a log file: "cva6/trace_hart_00.dasm"
. For every instruction that the simulation ran, it shows the cycle number, VPC, privilege mode, and instruction. It will be a very useful reference for this lab.
Notes:
- "Hart" means hardware thread, which is the same thing as a core.
- Simulation time should take no longer than 1 mintue.
- Sometimes the core randomly enters Debug mode. (Observe
TOP.ariane_testharness.i_ariane.i_cva6.debug_mode
). As long as the core returns to normal execution, you can ignore this. If the simulation never exits, then your code has a bug.
Additional resource: RISC-V Instruction Encoder/Decoder.
Note that "programs/vm/os.S"
demonstrates numerical labels with this line of code: blt t0, t1, 1b;
.
Numeric labels are used for local references. References to local labels are suffixed with f
for a forward reference or b
for a backwards reference (reference). They are most useful when creating loops or conditionals that don't need to be given a name, and don't need to called by another file.
- Show your modifications to
"rvfi_tracer.sv"
. - Show your modifications to
"os.S"
. - Draw a diagram of the hierarchical page table you created in your modified
"os.S"
.- Show/describe the contents of every valid PTE in each PT.
- Denote pointers from a PTE to another layer with an arrow to the corresponding PT.
- Show the contents of every valid physical frame in physical memory.
- Provide your
"trace_hart_00.dasm"
file, and highlight the following behaviors:- Enter
bootloader
in M-mode - Enter
OS
in S-mode - Enter user program 1 in U-mode; also provide its virtual and physical address
- Enter
s_trap
in S-mode - Renter
OS
in S-mode - Enter user program 2 in U-mode; also provide its virtual and physical address
- Renter
s_trap
in S-mode - Renter
OS
in S-mode - Enter
m_trap
in M-mode - Exit
- Enter
- Provide a screenshot of a waveform demonstrating how the MMU translates the user program's virtual address to its physical address. Note: The net hierarchical path to the MMU is
TOP.ariane_testharness.i_ariane.i_cva6.ex_stage_i.lsu_i.gen_mmu_sv39.i_cva6_mmu
.