Skip to content

Commit

Permalink
mstatus_ update bug fixed. Virtio used ring buffer index update bug f…
Browse files Browse the repository at this point in the history
…ixed.
  • Loading branch information
moizumi99 committed Aug 8, 2020
1 parent acd8d6d commit 3060c57
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 39 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ project(assembler_test)
set(CMAKE_CXX_STANDARD 14)

########### Needed for profiling.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0")
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0")
###########

include_directories(.)
Expand Down
4 changes: 2 additions & 2 deletions PeripheralEmulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ void PeripheralEmulator::VirtioEmulation() {
VirtioDiskAccess(kQueueAddress);
// Fire an interrupt.
// New standard has a way to suspend interrupt until index reaches a certain value, but not supported in xv6.

virtio_interrupt_ = true;
}

void PeripheralEmulator::read_desc(VRingDesc *desc, uint64_t desc_address, uint16_t desc_index) const {
Expand Down Expand Up @@ -316,7 +316,7 @@ void PeripheralEmulator::process_used_buffer(uint64_t used_buffer_address, uint1
memory_->Write32(used_buffer_address + 4 + current_used_index * 8, index);
memory_->Write32(used_buffer_address + 4 + current_used_index * 8 + 4, 3);
current_used_index = (current_used_index + 1) / queue_num_;
memory_->Write32(used_buffer_address + 4, current_used_index);
memory_->Write16(used_buffer_address + 2, current_used_index);
}

} // namespace RISCV_EMULATOR
6 changes: 3 additions & 3 deletions PeripheralEmulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ class PeripheralEmulator {
void VirtioInit();
void VirtioEmulation();
void SetDiskImage(std::shared_ptr<std::vector<uint8_t>> disk_image);
bool GetInterruptStatus() {return virtio_interrupt; }
void ClearInterruptStatus() {virtio_interrupt = false;}
bool GetInterruptStatus() {return virtio_interrupt_; }
void ClearInterruptStatus() { virtio_interrupt_ = false;}

private:
std::shared_ptr<MemoryWrapper> memory_;
Expand Down Expand Up @@ -119,7 +119,7 @@ class PeripheralEmulator {
uint64_t virtio_width_ = 0;
uint64_t virtio_data_ = 0;
int queue_num_ = 8;
bool virtio_interrupt = false;
bool virtio_interrupt_ = false;
void VirtioDiskAccess(uint64_t queue_address);
uint16_t get_desc_index(uint64_t avail_address) const;
void read_desc(VRingDesc *desc, uint64_t desc_address, uint16_t desc_index) const;
Expand Down
81 changes: 49 additions & 32 deletions RISCV_cpu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ void RiscvCpu::InitializeCsrs() {
csrs_[MISA] = (mxl_ << (xlen_ - 2)) | extensions;
if (mxl_ == 2) {
// For 64 bit mode, sxl and uxl are the same as mxl.
csrs_[MSTATUS] = (static_cast<uint64_t>(mxl_) << 34) | (static_cast<uint64_t>(mxl_) << 32);
mstatus_ = (static_cast<uint64_t>(mxl_) << 34) | (static_cast<uint64_t>(mxl_) << 32);
ApplyMstatusToCsr();
}
}

Expand Down Expand Up @@ -162,13 +163,13 @@ void RiscvCpu::Trap(int cause, bool interrupt) {
// Currently supported exceptions: page fault (12, 13, 15) and ecall (8, 9, 11).
// Currently supported interrupts: Supervisor Software Interrupt (1), Machine Timer Intetrupt (7)
assert((interrupt && (cause == MACHINE_TIMER_INTERRUPT || cause == SUPERVISOR_SOFTWARRE_INTERRUPT ||
cause == MACHINE_EXTERNAL_INTERRUPT)) ||
cause == SUPERVISOR_EXTERNAL_INTERRUPT)) ||
(!interrupt &
(cause == INSTRUCTION_PAGE_FAULT || cause == LOAD_PAGE_FAULT || cause == STORE_PAGE_FAULT ||
cause == ECALL_UMODE || cause == ECALL_SMODE || cause == ECALL_MMODE)));
if (interrupt && cause == MACHINE_EXTERNAL_INTERRUPT) {
std::cerr << "Machine External Interrupt" << std::endl;
}
// if (interrupt && cause == MACHINE_EXTERNAL_INTERRUPT) {
// std::cerr << "Machine External Interrupt" << std::endl;
// }
// Check the Machine Level Enable.
const uint64_t global_mie = bitcrop(mstatus_, 1, 3);
const uint64_t mie = csrs_[MIE];
Expand Down Expand Up @@ -238,12 +239,13 @@ void RiscvCpu::Trap(int cause, bool interrupt) {
// Copy old SIE (#1) to SPIE (#5). Then, disable SIE (#1).
mstatus_ = bitset(mstatus_, 1, 5, global_sie);
constexpr uint64_t kNewSie = 0;
mstatus_ = bitset(csrs_[SSTATUS], 1, 1, kNewSie);
mstatus_ = bitset(mstatus_, 1, 1, kNewSie);

// Save the current privilege mode to SPP (#12-11), and set the privilege to
// Supervisor.
const uint64_t new_spp = static_cast<int>(privilege_) & 1;
mstatus_ = bitset(mstatus_, 1, 8, new_spp);
const uint64_t new_mpp = PriviledgeToInt(privilege_);
mstatus_ = bitset(mstatus_, 1, 8, new_mpp);
ApplyMstatusToCsr();
privilege_ = PrivilegeMode::SUPERVISOR_MODE;
} else {
csrs_[MCAUSE] = cause | interrupt_cause_mask;
Expand All @@ -265,8 +267,9 @@ void RiscvCpu::Trap(int cause, bool interrupt) {

// Save the current privilege mode to MPP (#12-11), and set the privilege to
// Machine.
const uint64_t new_mpp = static_cast<int>(privilege_);
const uint64_t new_mpp = PriviledgeToInt(privilege_);
mstatus_ = bitset(mstatus_, 2, 11, new_mpp);
ApplyMstatusToCsr();
// Clear interrupt pending bit.
privilege_ = PrivilegeMode::MACHINE_MODE;
}
Expand Down Expand Up @@ -908,17 +911,18 @@ int RiscvCpu::RunCpu(uint64_t start_pc, bool verbose) {
continue;
}
CheckSoftwareInterrupt();
if (virtio_interrupt_) {
Trap(ExceptionCode::SUPERVISOR_EXTERNAL_INTERRUPT, kInterrupt);
virtio_interrupt_ = false;
continue;
}

ir_ = LoadCmd(pc_);
DumpDisassembly(verbose);
if (page_fault_) {
Trap(ExceptionCode::INSTRUCTION_PAGE_FAULT, kException);
continue;
}
if (virtio_interrupt_) {
Trap(ExceptionCode::MACHINE_EXTERNAL_INTERRUPT, kInterrupt);
virtio_interrupt_ = false;
continue;
}
// Decode. Mimick the HW behavior. (In HW, decode is in parallel.)
ctype_ = (ir_ & 0b11) != 0b11;

Expand Down Expand Up @@ -1172,6 +1176,7 @@ void RiscvCpu::ApplyMstatusToCsr() {
csrs_[USTATUS] = mstatus_ & ustatus_mask;
csrs_[SSTATUS] = mstatus_ & sstatus_mask;
csrs_[MSTATUS] = mstatus_;
// std::cerr << "pc_ = " << std::hex << pc_ << ", mstatus_ = " << mstatus_ << std::endl;
}

template <class T, int N>
Expand Down Expand Up @@ -1286,39 +1291,51 @@ PrivilegeMode RiscvCpu::IntToPrivilegeMode(int value) {
}
}

int RiscvCpu::PriviledgeToInt(PrivilegeMode priv) {
switch (priv) {
case PrivilegeMode::USER_MODE:
return 0;
case PrivilegeMode::SUPERVISOR_MODE:
return 1;
case PrivilegeMode::MACHINE_MODE:
return 3;
default:
throw std::out_of_range(std::to_string(static_cast<int>(priv)) + " is not appropriate privilege level");
}
}

void RiscvCpu::Mret() {
uint64_t mstatus = csrs_[MSTATUS];
// Set privilege mode to MPP.
uint64_t mpp = bitcrop(mstatus, 2, 11);
uint64_t mpp = bitcrop(mstatus_, 2, 11);
privilege_ = IntToPrivilegeMode(mpp);
// Set MIE to MPIE.
uint64_t mpie = bitcrop(mstatus, 1, 7);
mstatus = bitset(mstatus, 1, 3, mpie);
uint64_t mpie = bitcrop(mstatus_, 1, 7);
mstatus_ = bitset(mstatus_, 1, 3, mpie);
// Set MPIE to 1.
uint64_t new_mpie = 1;
mstatus = bitset(mstatus, 1, 7, new_mpie);
constexpr uint64_t kNewMpie = 1;
mstatus_ = bitset(mstatus_, 1, 7, kNewMpie);
// Set MPP to 0 as user mode is supported.
uint64_t new_mpp = 0;
mstatus = bitset(mstatus, 2, 11, new_mpp);
csrs_[MSTATUS] = mstatus;
constexpr uint64_t kNewMpp = 0;
mstatus_ = bitset(mstatus_, 2, 11, kNewMpp);
ApplyMstatusToCsr();
next_pc_ = csrs_[MEPC];
}

void RiscvCpu::Sret() {
uint64_t mstatus = csrs_[MSTATUS];
// Set privilege mode to SPP.
uint64_t spp = bitcrop(mstatus, 1, 8);
uint64_t spp = bitcrop(mstatus_, 1, 8);
privilege_ = IntToPrivilegeMode(spp);
// Set SIE to SPIE.
uint64_t spie = bitcrop(mstatus, 1, 5);
mstatus = bitset(mstatus, 1, 1, spie);
uint64_t spie = bitcrop(mstatus_, 1, 5);
mstatus_ = bitset(mstatus_, 1, 1, spie);
// Set SPIE to 1.
uint64_t new_spie = 1;
mstatus = bitset(mstatus, 1, 5, new_spie);
constexpr uint64_t kNewSpie = 1;
mstatus_ = bitset(mstatus_, 1, 5, kNewSpie);
// Set SPP to 0
uint64_t new_spp = 0;
mstatus = bitset(mstatus, 2, 8, new_spp);
csrs_[MSTATUS] = mstatus;
constexpr uint64_t kNewSpp = 0;
mstatus_ = bitset(mstatus_, 2, 8, kNewSpp);
csrs_[MSTATUS] = mstatus_;
ApplyMstatusToCsr();
next_pc_ = csrs_[SEPC];
}

Expand Down

0 comments on commit 3060c57

Please sign in to comment.