* Copyright 2020-2021, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* X512 <danger_mail@list.ru>
*/
#ifndef _RISCV64VMTRANSLATIONMAP_H_
#define _RISCV64VMTRANSLATIONMAP_H_
#include <atomic>
#include <vm/VMTranslationMap.h>
#include <arch_cpu_defs.h>
#include <kernel/smp.h>
enum {
PAGE_INVALIDATE_CACHE_SIZE = 64
};
struct RISCV64VMTranslationMap: public VMTranslationMap {
RISCV64VMTranslationMap(bool kernel,
phys_addr_t pageTable = 0);
virtual ~RISCV64VMTranslationMap();
virtual bool Lock();
virtual void Unlock();
virtual addr_t MappedSize() const;
virtual size_t MaxPagesNeededToMap(addr_t start,
addr_t end) const;
virtual status_t Map(addr_t virtualAddress,
phys_addr_t physicalAddress,
uint32 attributes, uint32 memoryType,
vm_page_reservation* reservation);
virtual status_t Unmap(addr_t start, addr_t end);
virtual status_t UnmapPage(VMArea* area, addr_t address,
bool updatePageQueue,
bool deletingAddressSpace, uint32* _flags);
virtual void UnmapPages(VMArea* area, addr_t base,
size_t size, bool updatePageQueue,
bool deletingAddressSpace);
virtual status_t Query(addr_t virtualAddress,
phys_addr_t* _physicalAddress,
uint32* _flags);
virtual status_t QueryInterrupt(addr_t virtualAddress,
phys_addr_t* _physicalAddress,
uint32* _flags);
virtual status_t Protect(addr_t base, addr_t top,
uint32 attributes, uint32 memoryType);
void SetFlags(addr_t virtualAddress,
uint32 flags);
virtual status_t ClearFlags(addr_t virtualAddress,
uint32 flags);
virtual bool ClearAccessedAndModified(
VMArea* area, addr_t address,
bool unmapIfUnaccessed,
bool& _modified);
virtual void Flush();
virtual void DebugPrintMappingInfo(addr_t virtualAddress);
virtual bool DebugGetReverseMappingInfo(
phys_addr_t physicalAddress,
ReverseMappingInfoCallback& callback);
inline phys_addr_t PageTable();
inline uint64 Satp();
status_t MemcpyToMap(addr_t to, const char *from,
size_t size);
status_t MemcpyFromMap(char *to, addr_t from,
size_t size);
status_t MemsetToMap(addr_t to, char c, size_t count);
ssize_t StrlcpyFromMap(char *to, addr_t from,
size_t size);
ssize_t StrlcpyToMap(addr_t to, const char *from,
size_t size);
inline CPUSet& ActiveOnCpus();
inline void InvalidatePage(addr_t address);
private:
std::atomic<Pte>* LookupPte(addr_t virtAdr, bool alloc,
vm_page_reservation* reservation);
phys_addr_t LookupAddr(addr_t virtAdr);
bool fIsKernel;
phys_addr_t fPageTable;
uint64 fPageTableSize;
CPUSet fActiveOnCpus;
int fInvalidPagesCount;
addr_t fInvalidPages[PAGE_INVALIDATE_CACHE_SIZE];
bool fInvalidCode;
};
inline phys_addr_t
RISCV64VMTranslationMap::PageTable()
{
return fPageTable;
}
inline uint64
RISCV64VMTranslationMap::Satp()
{
SatpReg satp;
satp.ppn = fPageTable / B_PAGE_SIZE;
satp.asid = 0;
satp.mode = satpModeSv39;
return satp.val;
}
CPUSet&
RISCV64VMTranslationMap::ActiveOnCpus()
{
return fActiveOnCpus;
}
void
RISCV64VMTranslationMap::InvalidatePage(addr_t address)
{
if (fInvalidPagesCount < PAGE_INVALIDATE_CACHE_SIZE)
fInvalidPages[fInvalidPagesCount] = address;
fInvalidPagesCount++;
}
struct RISCV64VMPhysicalPageMapper: public VMPhysicalPageMapper {
RISCV64VMPhysicalPageMapper();
virtual ~RISCV64VMPhysicalPageMapper();
virtual status_t GetPage(phys_addr_t physicalAddress,
addr_t* _virtualAddress,
void** _handle);
virtual status_t PutPage(addr_t virtualAddress,
void* handle);
virtual status_t GetPageCurrentCPU(
phys_addr_t physicalAddress,
addr_t* _virtualAddress,
void** _handle);
virtual status_t PutPageCurrentCPU(addr_t virtualAddress,
void* _handle);
virtual status_t GetPageDebug(phys_addr_t physicalAddress,
addr_t* _virtualAddress,
void** _handle);
virtual status_t PutPageDebug(addr_t virtualAddress,
void* handle);
virtual status_t MemsetPhysical(phys_addr_t address, int value,
phys_size_t length);
virtual status_t MemcpyFromPhysical(void* to, phys_addr_t from,
size_t length, bool user);
virtual status_t MemcpyToPhysical(phys_addr_t to,
const void* from, size_t length,
bool user);
virtual void MemcpyPhysicalPage(phys_addr_t to,
phys_addr_t from);
};
#endif