comments fixed

This commit is contained in:
Kirill Akulich 2022-05-29 22:13:22 +03:00
parent 5821f2a904
commit a29caf9451
9 changed files with 158 additions and 54 deletions

View file

@ -120,37 +120,27 @@ MemoryUnit::MemoryUnit(uint64_t pageSize, uint64_t addrBytes, bool disableVm)
ram_ = nullptr;
}
MemoryUnit::MemoryUnit(uint64_t pageSize, uint64_t addrBytes, uint64_t rootPageNumber)
: pageSize_(pageSize)
, addrBytes_(addrBytes)
, disableVM_(false) {
tlb_[0] = TLBEntry(0, 077);
}
void MemoryUnit::attach(MemDevice &m, uint64_t start, uint64_t end) {
decoder_.map(start, end, m);
}
MemoryUnit::TLBEntry MemoryUnit::tlbLookup(uint64_t vAddr, uint32_t flagMask) {
auto iter = tlb_.find(vAddr / pageSize_);
std::cout<< "Looking for addr" <<std::bitset<64>(vAddr)<<std::endl;
if (iter != tlb_.end()) {
if (iter->second.flags & flagMask){
iter->second.updateAccessBit(true);
return iter->second;
}
else {
std::cout<<"Security viotion"<<std::endl;
throw TlbMiss(vAddr);
}
} else {
std::cout<<"Address not found"<<vAddr<<std::endl;
throw TlbMiss(vAddr);
}
}
void MemoryUnit::read(void *data, uint64_t addr, uint64_t size, bool sup) {
updateTLBIfNeeded();
accessBitUpdate();
uint64_t pAddr;
if (disableVM_) {
pAddr = addr;
@ -158,25 +148,23 @@ void MemoryUnit::read(void *data, uint64_t addr, uint64_t size, bool sup) {
uint32_t flagMask = sup ? 8 : 1;
try{
TLBEntry t = this->tlbLookup(addr, flagMask);
pAddr = t.pfn * pageSize_ + addr % pageSize_;
std::cout<<"Tlb hit. Adress: "<<std::bitset<64>(addr)<<"Physical address"<<std::endl;
pAddr = t.pfn * pageSize_ + addr % pageSize_;
}
catch(TlbMiss e){
std::cout<<"Tlb miss Address: "<< std::bitset<64>(addr)<< std::endl;
pAddr = handleTlbMiss(addr);
std::cout<<"Translate vAddr: "<< std::bitset<64>(addr)<< "To: "<< std::bitset<64>(pAddr) << std::endl;
}
}
return decoder_.read(data, pAddr, size);
}
uint64_t MemoryUnit::translateVirtualToPhysical(uint64_t vAddr, uint32_t flagMask){
MultibaleAddressBase* virtualAddress = virtualAddressFactory_->createMultitableAddressFromBits(vAddr);
uint64_t MemoryUnit::translateVirtualToPhysical(uint64_t vAddr, uint32_t flagMask){
MultitableAddressBase* virtualAddress = virtualAddressFactory_->createMultitableAddressFromBits(vAddr);
uint64_t currentPageNumber = supervisorContainer_->satp.getRootPageNumber();
uint64_t address;
uint64_t pte;
uint64_t pAddr;
for(int i = virtualAddress->levelCount() - 1;i >=0; i-- ){
for (int i = virtualAddress->levelCount() - 1; i >= 0; i--){
address = (currentPageNumber << 12) + (virtualAddress->getOffsetForLevel(i))*sizeof(uint64_t);
this->ram_->read(&pte, address, sizeof(uint64_t));
TablePageEntryBase tableEntry(pte);
@ -192,7 +180,7 @@ uint64_t MemoryUnit::translateVirtualToPhysical(uint64_t vAddr, uint32_t flagMa
}
}else{
// return invalid address
supervisorContainer_->scause.setPageFaultExceptionAccured(true);
supervisorContainer_->scause.setPageFaultExceptionOccured(true);
supervisorContainer_->stval.updateValue(vAddr);
return -1;
}
@ -205,7 +193,7 @@ uint64_t MemoryUnit:: handlePageFault(){
uint64_t causeVAddr = supervisorContainer_->stval.value();
uint64_t currentPageNumber = supervisorContainer_->satp.getRootPageNumber();
auto vAddr = virtualAddressFactory_->createMultitableAddressFromBits(causeVAddr);
for(int i=vAddr->levelCount()-1;i>=1;i--){
for (int i = vAddr->levelCount()-1; i >= 1; i--){
uint64_t address = (currentPageNumber << 12) + (vAddr->getOffsetForLevel(i))*sizeof(uint64_t);
uint64_t pteBits;
ram_->read(&pteBits,address, sizeof(uint64_t));
@ -216,7 +204,7 @@ uint64_t MemoryUnit:: handlePageFault(){
else{
uint64_t newTableAddress;
uint16_t flags=1;
newTableAddress = allocate_translation_table();
newTableAddress = allocateTranslationTable();
uint64_t newTableEntry = (newTableAddress << 8) | flags;
this->ram_->write(&newTableEntry, address, sizeof(uint64_t));
@ -230,13 +218,13 @@ uint64_t MemoryUnit:: handlePageFault(){
uint64_t newRAMPageNumber = ram_->getFirstFreeTable();
uint64_t newPageAddress = newRAMPageNumber << 12;
uint8_t* virtualPageData = new uint8_t[pageSize_];
requestVirtualPage(virtualPageData, causeVAddr);
requestVirtualPage(virtualPageData, (causeVAddr>>12)<<12);
ram_->write(virtualPageData, newPageAddress, pageSize_);
uint64_t newTableEntry = (newRAMPageNumber << 8) | flags;
ram_->write(&newTableEntry, address, sizeof(uint64_t));
uint64_t pAddr = (newPageAddress) | pageOffset;
this->supervisorContainer_->scause.setPageFaultExceptionAccured(false);
this->supervisorContainer_->scause.setPageFaultExceptionOccured(false);
return pAddr;
}
@ -244,11 +232,11 @@ void MemoryUnit::requestVirtualPage(uint8_t* data, uint64_t virtualAddress){
virtualDevice_->read(data, virtualAddress, pageSize_);
}
uint64_t MemoryUnit::allocate_translation_table(){
uint64_t MemoryUnit::allocateTranslationTable(){
uint64_t newPageAddress = this->ram_->getFirstFreeTable();
uint8_t zeroByte = 0;
uint64_t currentPageAddress = newPageAddress << 12;
for(int i=0;i< pageSize_;i++){
for (int i = 0; i < pageSize_; i++){
this->ram_->write(&zeroByte, currentPageAddress, sizeof(uint8_t));
currentPageAddress+= 1;
}
@ -256,9 +244,8 @@ uint64_t MemoryUnit::allocate_translation_table(){
return newPageAddress;
}
void MemoryUnit::write(const void *data, uint64_t addr, uint64_t size, bool sup) {
updateTLBIfNeeded();
accessBitUpdate();
uint64_t pAddr;
if (disableVM_) {
pAddr = addr;
@ -277,15 +264,14 @@ void MemoryUnit::write(const void *data, uint64_t addr, uint64_t size, bool sup)
}
void MemoryUnit::tlbAdd(uint64_t virt, uint64_t phys, uint32_t flags) {
MultibaleAddressBase* vAddr =virtualAddressFactory_->createMultitableAddressFromBits(virt);
MultitableAddressBase* vAddr = virtualAddressFactory_->createMultitableAddressFromBits(virt);
TLBEntry entry(phys, flags);
std::cout<<"[TlbAdd] vAddr:"<<std::bitset<64>(vAddr->getVirtualAddress())<<"->"<<std::bitset<64>(phys)<<std::endl;
entry.updateAccessBit(true);
tlb_[vAddr->getVirtualAddress()] = entry;
}
void MemoryUnit::tlbRm() {
for(auto& it: tlb_){
void MemoryUnit::tlbEvict() {
for (auto& it : tlb_){
if(!it.second.isAccessBitSet){
tlb_.erase(it.first);
}
@ -321,7 +307,7 @@ void MemoryUnit::setupAddressFactories(){
}
}
void MemoryUnit::updateTLBIfNeeded(){
void MemoryUnit::accessBitUpdate(){
if(memoryAccessCount_ == RefreshTblRate){
memoryAccessCount_ = 0;
}
@ -339,16 +325,16 @@ void MemoryUnit::updateTLBIfNeeded(){
uint64_t MemoryUnit::handleTlbMiss(uint64_t vaddr)
{
if(tlb_.size() == maxPageTableEntriesCount){
tlbRm();
tlbEvict();
}
uint32_t flagMask = 1;
uint32_t flagMask = 1;
uint64_t pAddr = translateVirtualToPhysical(vaddr,flagMask);
//check if page not translated because of page fault
if(supervisorContainer_->scause.checkIsPageFaultExceptionAccured()){
if(supervisorContainer_->scause.checkIsPageFaultExceptionOccured()){
pAddr = handlePageFault();
}
tlbAdd(vaddr, pAddr / pageSize_, flagMask);
return pAddr;
}

View file

@ -106,9 +106,9 @@ class TablePageEntryBase{
};
class MultibaleAddressBase{
class MultitableAddressBase{
public:
MultibaleAddressBase(uint64_t addr){
MultitableAddressBase(uint64_t addr){
address_ = addr;
}
@ -144,7 +144,7 @@ class MultibaleAddressBase{
class VirtualAddressFactoryBase{
public:
virtual MultibaleAddressBase* createMultitableAddressFromBits(uint64_t addr) = 0;
virtual MultitableAddressBase* createMultitableAddressFromBits(uint64_t addr) = 0;
};
class PhysicalTableEntryFactoryBase{
@ -225,7 +225,6 @@ public:
};
MemoryUnit(uint64_t pageSize, uint64_t addrBytes, bool disableVm = false);
MemoryUnit(uint64_t pageSize, uint64_t addrBytes, uint64_t rootAddress);
void attach(MemDevice &m, uint64_t start, uint64_t end);
void read(void *data, uint64_t addr, uint64_t size, bool sup);
void write(const void *data, uint64_t addr, uint64_t size, bool sup);
@ -235,7 +234,9 @@ public:
void requestVirtualPage(uint8_t* data,uint64_t virtualAddr);
void tlbAdd(uint64_t virt, uint64_t phys, uint32_t flags);
void tlbRm();
void tlbEvict();
void tlbRm(uint64_t va);
void tlbFlush() {
tlb_.clear();
}
@ -287,11 +288,11 @@ private:
uint64_t translateVirtualToPhysical(uint64_t vAddr, uint32_t flagMask);
TLBEntry tlbLookup(uint64_t vAddr, uint32_t flagMask);
void updateTLBIfNeeded();
void accessBitUpdate();
void markTableAccessed(uint64_t vAddr);
void markTableExecutable(uint64_t vAddr);
uint64_t handlePageFault();
uint64_t allocate_translation_table();
uint64_t allocateTranslationTable();
void setupAddressFactories();
uint64_t handleTlbMiss(uint64_t vaddr);
@ -329,10 +330,10 @@ class SV39TablePageEntry: public TablePageEntryBase
SV39TablePageEntry(uint64_t pte): TablePageEntryBase(pte){};
};
class SV39VirtualAddress: public MultibaleAddressBase
class SV39VirtualAddress: public MultitableAddressBase
{
public:
SV39VirtualAddress(uint64_t address):MultibaleAddressBase(address){}
SV39VirtualAddress(uint64_t address):MultitableAddressBase(address){}
int levelCount() override { return 3;}
int pageOffsetLength() override { return 12;}
protected:
@ -347,7 +348,7 @@ class SV39PageTableEntryFactory:public PhysicalTableEntryFactoryBase{
class SV39VirtualAddressFactory: public VirtualAddressFactoryBase{
public:
MultibaleAddressBase* createMultitableAddressFromBits(uint64_t addr) override{
MultitableAddressBase* createMultitableAddressFromBits(uint64_t addr) override{
return new SV39VirtualAddress(addr);
}
};

View file

@ -0,0 +1,41 @@
#include "processorRegs.h"
using namespace vortex;
SATP:: SATP(VirtualAddressTranslationMode mode){
updateMode(mode);
}
void SATP::updateMode(VirtualAddressTranslationMode mode){
uint64_t bitsMode = mode;
regBits_ =(regBits_ & (((uint64_t)1 << 60)-1)) | (bitsMode<< 59);
}
void SATP::updateRootPageTable(uint64_t ppn){
regBits_ = ((regBits_ >> rootPageLength) << rootPageLength)
| (ppn & ((((uint64_t)1 << rootPageLength) -1)));
}
uint64_t SATP::getRootPageNumber(){
auto rootNumber = regBits_ & (((uint64_t)1 << rootPageLength) -1);
return rootNumber;
}
bool SCAUSE::checkIsPageFaultExceptionOccured(){
return isBitSet(pageFaultBitNumber);
}
void SCAUSE::setPageFaultExceptionOccured(bool isAccured){
setBit(isAccured, pageFaultBitNumber);
}
void SCAUSE::setBit(bool isSet, int number){
regBits_ = regBits_ | ((uint64_t) 1 << number);
}
bool SCAUSE::isBitSet(int number){
return (regBits_ & ((uint64_t)1 << number)) !=0;
}

View file

@ -0,0 +1,76 @@
#pragma once
#include <cstdint>
namespace vortex{
// according to spec https://github.com/riscv/virtual-memory/blob/main/specs/668-Svinval.pdf
// mode is defined in the followig way:
// - 0 = No translation or protection
// - 1-7 = Reserved for standart use
// - 8 = SV39 Page-based 39-bit virtual addressing
// - 9 = SV48 Page based 48-bit virtual addressing
// - 10 = SV57 Page-based 57-bit virtual addressing
// - 11 = SV64 Page based virtual addressing
// - 12 - 13 = Reserved for standart use
// - 14 - 15 = Designed for custom use
enum VirtualAddressTranslationMode:uint8_t{
NoTranslation = 0,
SV39 = 8
};
class SATP{
public:
SATP(VirtualAddressTranslationMode mode);
void updateMode(VirtualAddressTranslationMode mode);
void updateRootPageTable(uint64_t ppn);
VirtualAddressTranslationMode Mode(){
return static_cast<VirtualAddressTranslationMode>(regBits_ >> (length - modeBitsLength-1));
}
uint64_t getRootPageNumber();
private:
static const int modeBitsLength = 4;
static const int rootPageLength = 44;
static const int length = 64;
uint64_t regBits_;
};
class SCAUSE{
public:
void setPageFaultExceptionOccured(bool isAccured);
bool checkIsPageFaultExceptionOccured();
private:
void setBit(bool isSet, int number);
bool isBitSet(int number);
static const int pageFaultBitNumber = 12;
uint64_t regBits_;
};
class STVAL{
public:
void updateValue(uint64_t value){
regBits_ = value;
};
uint64_t value(){
return regBits_;
}
private:
uint64_t regBits_;
};
class SupervisorRegisterContainer{
public:
SupervisorRegisterContainer(VirtualAddressTranslationMode mode):
satp(mode){};
// according to spec https://github.com/riscv/virtual-memory/blob/main/specs/668-Svinval.pdf
// these registers are used to control virtual page translation.
// Satp is used to define virtual address/page table entry/root page table
// Scause defines reason why exception/interruption accured
// Stval register is used to get the reason why exception is accured
SATP satp;
SCAUSE scause;
STVAL stval;
};
}

View file

@ -171,7 +171,7 @@ void Core::attach_ram(RAM* ram) {
mmu_.attachRAM(*ram, 0, 0xFFFFFFFF);
}
void Core::attach_virtual_device(VirtualDevice* device){
void Core::attachVirtualDevice(VirtualDevice* device){
mmu_.attachVirtualDevice(*device);
}

View file

@ -74,7 +74,7 @@ public:
void attach_ram(RAM* ram);
void attach_virtual_device(VirtualDevice* virtualDevice);
void attachVirtualDevice(VirtualDevice* virtualDevice);
void attach_supervisor_regs(SupervisorRegisterContainer* supervysorRegs);

View file

@ -76,7 +76,7 @@ int main(int argc, char **argv) {
// attach memory module
processor.attach_ram(&ram);
processor.attach_virtual_device(& virtualDevice);
processor.attachVirtualDevice(& virtualDevice);
// run simulation
exitcode = processor.run();

View file

@ -143,9 +143,9 @@ public:
}
}
void attach_virtual_device(VirtualDevice* virtualDevice){
void attachVirtualDevice(VirtualDevice* virtualDevice){
for (auto core: cores_){
core->attach_virtual_device(virtualDevice);
core->attachVirtualDevice(virtualDevice);
}
}
@ -186,8 +186,8 @@ void Processor::attach_ram(RAM* mem) {
impl_->attach_ram(mem);
}
void Processor::attach_virtual_device(VirtualDevice* device){
impl_->attach_virtual_device(device);
void Processor::attachVirtualDevice(VirtualDevice* device){
impl_->attachVirtualDevice(device);
}
int Processor::run() {

View file

@ -12,7 +12,7 @@ public:
~Processor();
void attach_ram(RAM* mem);
void attach_virtual_device(VirtualDevice* virtualDevice);
void attachVirtualDevice(VirtualDevice* virtualDevice);
int run();