1/*
2 * Copyright 2020-2021, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *   X512 <danger_mail@list.ru>
7 */
8#ifndef _RISCV64VMTRANSLATIONMAP_H_
9#define _RISCV64VMTRANSLATIONMAP_H_
10
11
12#include <atomic>
13
14#include <vm/VMTranslationMap.h>
15#include <arch_cpu_defs.h>
16#include <kernel/smp.h>
17
18
19enum {
20	PAGE_INVALIDATE_CACHE_SIZE = 64
21};
22
23
24struct RISCV64VMTranslationMap: public VMTranslationMap {
25								RISCV64VMTranslationMap(bool kernel,
26									phys_addr_t pageTable = 0);
27	virtual						~RISCV64VMTranslationMap();
28
29	virtual	bool				Lock();
30	virtual	void				Unlock();
31
32	virtual	addr_t				MappedSize() const;
33	virtual	size_t				MaxPagesNeededToMap(addr_t start,
34									addr_t end) const;
35
36	virtual	status_t			Map(addr_t virtualAddress,
37									phys_addr_t physicalAddress,
38									uint32 attributes, uint32 memoryType,
39									vm_page_reservation* reservation);
40	virtual	status_t			Unmap(addr_t start, addr_t end);
41
42	virtual	status_t			DebugMarkRangePresent(addr_t start, addr_t end,
43									bool markPresent);
44
45	virtual	status_t			UnmapPage(VMArea* area, addr_t address,
46									bool updatePageQueue);
47	virtual	void				UnmapPages(VMArea* area, addr_t base,
48									size_t size, bool updatePageQueue);
49	virtual	void				UnmapArea(VMArea* area,
50									bool deletingAddressSpace,
51									bool ignoreTopCachePageFlags);
52
53	virtual	status_t			Query(addr_t virtualAddress,
54									phys_addr_t* _physicalAddress,
55									uint32* _flags);
56	virtual	status_t			QueryInterrupt(addr_t virtualAddress,
57									phys_addr_t* _physicalAddress,
58									uint32* _flags);
59
60	virtual	status_t			Protect(addr_t base, addr_t top,
61									uint32 attributes, uint32 memoryType);
62			status_t			ProtectPage(VMArea* area, addr_t address,
63									uint32 attributes);
64			status_t			ProtectArea(VMArea* area,
65									uint32 attributes);
66
67			void				SetFlags(addr_t virtualAddress,
68									uint32 flags);
69
70	virtual	status_t			ClearFlags(addr_t virtualAddress,
71									uint32 flags);
72
73	virtual	bool				ClearAccessedAndModified(
74									VMArea* area, addr_t address,
75									bool unmapIfUnaccessed,
76									bool& _modified);
77
78	virtual	void				Flush();
79
80	virtual	void				DebugPrintMappingInfo(addr_t virtualAddress);
81	virtual	bool				DebugGetReverseMappingInfo(
82									phys_addr_t physicalAddress,
83									ReverseMappingInfoCallback& callback);
84
85	inline	phys_addr_t			PageTable();
86	inline	uint64				Satp();
87
88			status_t			MemcpyToMap(addr_t to, const char *from,
89									size_t size);
90			status_t			MemcpyFromMap(char *to, addr_t from,
91									size_t size);
92			status_t			MemsetToMap(addr_t to, char c, size_t count);
93			ssize_t				StrlcpyFromMap(char *to, addr_t from,
94									size_t size);
95			ssize_t				StrlcpyToMap(addr_t to, const char *from,
96									size_t size);
97
98	inline	CPUSet&				ActiveOnCpus();
99	inline	void				InvalidatePage(addr_t address);
100
101private:
102			std::atomic<Pte>*	LookupPte(addr_t virtAdr, bool alloc,
103									vm_page_reservation* reservation);
104			phys_addr_t			LookupAddr(addr_t virtAdr);
105
106			bool				fIsKernel;
107			phys_addr_t			fPageTable;
108			uint64				fPageTableSize; // in page units
109			CPUSet				fActiveOnCpus;
110			int					fInvalidPagesCount;
111			addr_t				fInvalidPages[PAGE_INVALIDATE_CACHE_SIZE];
112			bool				fInvalidCode;
113};
114
115
116inline phys_addr_t
117RISCV64VMTranslationMap::PageTable()
118{
119	return fPageTable;
120}
121
122
123inline uint64
124RISCV64VMTranslationMap::Satp()
125{
126	SatpReg satp;
127	satp.ppn = fPageTable / B_PAGE_SIZE;
128	satp.asid = 0;
129	satp.mode = satpModeSv39;
130	return satp.val;
131}
132
133
134CPUSet&
135RISCV64VMTranslationMap::ActiveOnCpus()
136{
137	return fActiveOnCpus;
138}
139
140
141void
142RISCV64VMTranslationMap::InvalidatePage(addr_t address)
143{
144	if (fInvalidPagesCount < PAGE_INVALIDATE_CACHE_SIZE)
145		fInvalidPages[fInvalidPagesCount] = address;
146
147	fInvalidPagesCount++;
148}
149
150
151struct RISCV64VMPhysicalPageMapper: public VMPhysicalPageMapper {
152								RISCV64VMPhysicalPageMapper();
153	virtual						~RISCV64VMPhysicalPageMapper();
154
155	virtual	status_t			GetPage(phys_addr_t physicalAddress,
156									addr_t* _virtualAddress,
157									void** _handle);
158	virtual	status_t			PutPage(addr_t virtualAddress,
159									void* handle);
160
161	virtual	status_t			GetPageCurrentCPU(
162									phys_addr_t physicalAddress,
163									addr_t* _virtualAddress,
164									void** _handle);
165	virtual	status_t			PutPageCurrentCPU(addr_t virtualAddress,
166									void* _handle);
167
168	virtual	status_t			GetPageDebug(phys_addr_t physicalAddress,
169									addr_t* _virtualAddress,
170									void** _handle);
171	virtual	status_t			PutPageDebug(addr_t virtualAddress,
172									void* handle);
173
174	virtual	status_t			MemsetPhysical(phys_addr_t address, int value,
175									phys_size_t length);
176	virtual	status_t			MemcpyFromPhysical(void* to, phys_addr_t from,
177									size_t length, bool user);
178	virtual	status_t			MemcpyToPhysical(phys_addr_t to,
179									const void* from, size_t length,
180									bool user);
181	virtual	void				MemcpyPhysicalPage(phys_addr_t to,
182									phys_addr_t from);
183};
184
185
186#endif	// _RISCV64VMTRANSLATIONMAP_H_
187