-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathcvm.h
More file actions
277 lines (236 loc) · 7.82 KB
/
cvm.h
File metadata and controls
277 lines (236 loc) · 7.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
//
// Project: CMiniLang
// Author: bajdcc
//
#ifndef CMINILANG_VM_H
#define CMINILANG_VM_H
#include <memory>
#include <vector>
#include <unordered_set>
#include <chrono>
#include <deque>
#include "types.h"
#include "memory.h"
#include "cmem.h"
#include "cvfs.h"
#include "cnet.h"
namespace clib {
// Website: https://github.com/bajdcc/MiniOS
/* virtual memory management */
// 虚存分配(二级页表分配方式)
// 参考:http://wiki.osdev.org/Paging
// 对于一个32位虚拟地址(virtual address)
// 32-22: 页目录号 | 21-12: 页表号 | 11-0: 页内偏移
// http://www.360doc.com/content/11/0804/10/7204565_137844381.shtml
/* 4k per page */
#define PAGE_SIZE 4096
/* 页掩码,取高20位 */
#define PAGE_MASK 0xfffff000
/* 地址对齐 */
#define PAGE_ALIGN_DOWN(x) ((x) & PAGE_MASK)
#define PAGE_ALIGN_UP(x) (((x) + PAGE_SIZE - 1) & PAGE_MASK)
/* 分析地址 */
#define PDE_INDEX(x) (((x) >> 22) & 0x3ff) // 获得地址对应的页目录号
#define PTE_INDEX(x) (((x) >> 12) & 0x3ff) // 获得页表号
#define OFFSET_INDEX(x) ((x) & 0xfff) // 获得页内偏移
// 页目录项、页表项用uint32表示即可
typedef uint32_t pde_t;
typedef uint32_t pte_t;
/* 页目录大小 1024 */
#define PDE_SIZE (PAGE_SIZE/sizeof(pte_t))
/* 页表大小 1024 */
#define PTE_SIZE (PAGE_SIZE/sizeof(pde_t))
/* 页表总数 1024*PTE_SIZE*PAGE_SIZE = 4G */
#define PTE_COUNT 1024
/* CPU */
#define CR0_PG 0x80000000
/* pde&pdt attribute */
#define PTE_P 0x1 // 有效位 Present
#define PTE_R 0x2 // 读写位 Read/Write, can be read&write when set
#define PTE_U 0x4 // 用户位 User / Kern
#define PTE_K 0x0 // 内核位 User / Kern
#define PTE_W 0x8 // 写回 Write through
#define PTE_D 0x10 // 不缓存 Cache disable
#define PTE_A 0x20 // 可访问 Accessed
#define PTE_S 0x40 // Page size, 0 for 4kb pre page
#define PTE_G 0x80 // Ignored
/* 用户代码段基址 */
#define USER_BASE 0xc0000000
/* 用户数据段基址 */
#define DATA_BASE 0xd0000000
/* 用户栈基址 */
#define STACK_BASE 0xe0000000
/* 用户堆基址 */
#define HEAP_BASE 0xf0000000
/* 段掩码 */
#define SEGMENT_MASK 0x0fffffff
/* 物理内存(单位:16B),越多越好! */
#define PHY_MEM (256 * 1024)
#define PE_MAGIC "ccos"
#define U2K(addr) ((uint) ((addr) << 20) & 0x0ff00000)
#define K2U(addr) ((uint) ((addr) & 0x000fffff))
#define TASK_NUM 256
#define HANDLE_NUM 1024
#define BIG_DATA_NUM 512
#define READ_EOF 0x1000
class cvm : public imem, public vfs_func_t, public vfs_stream_call {
public:
cvm();
~cvm();
cvm(const cvm &) = delete;
cvm &operator=(const cvm &) = delete;
int load(const string_t &path, const std::vector<byte> &file, const std::vector<string_t> &args);
bool run(int cycle, int &cycles);
void map_page(uint32_t addr, uint32_t id) override;
void as_root(bool flag);
bool read_vfs(const string_t &path, std::vector<byte> &data) const;
bool write_vfs(const string_t &path, const std::vector<byte> &data);
vfs_stream_t stream_type(const string_t &path) const override;
string_t stream_callback(const string_t &path) override;
vfs_node_dec *stream_create(const vfs_mod_query *mod, vfs_stream_t type, const string_t &path) override;
int stream_index(vfs_stream_t type) override;
string_t stream_net(vfs_stream_t type, const string_t &path) override;
private:
// 申请页框
uint32_t pmm_alloc(bool reusable = true);
// 初始化页表
void vmm_init();
// 虚页映射
void vmm_map(uint32_t va, uint32_t pa, uint32_t flags);
// 解除映射
void vmm_unmap(uint32_t va);
// 查询分页情况
int vmm_ismap(uint32_t va, uint32_t *pa) const;
template<class T = int>
T vmm_get(uint32_t va) const;
string_t vmm_getstr(uint32_t va) const;
template<class T = int>
T vmm_set(uint32_t va, T);
void vmm_setstr(uint32_t va, const string_t &str);
uint32_t vmm_malloc(uint32_t size);
uint32_t vmm_free(uint32_t addr);
uint32_t vmm_memset(uint32_t va, uint32_t value, uint32_t count);
uint32_t vmm_memcmp(uint32_t src, uint32_t dst, uint32_t count);
template<class T = int>
void vmm_pushstack(uint32_t &sp, T value);
template<class T = int>
T vmm_popstack(uint32_t &sp);
void error(const string_t &) const;
void exec(int cycle, int &cycles);
void destroy(int id);
int exec_file(const string_t &path);
int fork();
char *output_fmt(int id) const;
int output(int id);
bool interrupt();
bool math(int id);
void cast();
void init_fs();
enum handle_type {
h_none,
h_file,
};
int new_pid();
int new_handle(handle_type);
void destroy_handle(int handle);
private:
/* 内核页表 = PTE_SIZE*PAGE_SIZE */
pde_t *pgd_kern;
/* 内核页表内容 = PTE_COUNT*PTE_SIZE*PAGE_SIZE */
pde_t *pte_kern;
/* 物理内存(1 block=16B) */
memory_pool<PHY_MEM> memory;
/* 页表 */
pde_t *pgdir{nullptr};
int pids{0};
enum ctx_flag_t {
CTX_VALID = 1 << 0,
CTX_KERNEL = 1 << 1,
CTX_USER_MODE = 1 << 2,
CTX_FOREGROUND = 1 << 3,
};
enum ctx_state_t {
CTS_RUNNING,
CTS_WAIT,
CTS_ZOMBIE,
CTS_DEAD,
};
static const char *state_string(ctx_state_t);
struct context_t {
uint flag;
int id;
int parent;
std::unordered_set<int> child;
ctx_state_t state;
string_t path;
uint mask;
uint entry;
uint poolsize;
uint stack;
uint data;
uint base;
uint heap;
uint pc;
union {
int _i;
uint _ui;
void *_p;
float _f;
double _d;
int64 _q;
uint64 _uq;
struct {
int _1, _2;
} _u;
short _s;
char _c;
byte big_data[BIG_DATA_NUM];
} ax;
uint bp;
uint sp;
bool debug;
std::vector<byte> file;
std::vector<uint32_t> allocation;
std::vector<uint32_t> data_mem;
std::vector<uint32_t> text_mem;
std::vector<uint32_t> stack_mem;
std::unique_ptr<cmem> pool;
// SYSTEM CALL
std::chrono::system_clock::time_point record_now;
decimal waiting_ms;
int input_redirect;
int output_redirect;
bool input_stop;
std::deque<char> input_queue;
std::unordered_set<int> handles;
};
context_t *ctx{nullptr};
int available_tasks{0};
std::array<context_t, TASK_NUM> tasks;
cvfs fs;
cnet net;
struct handle_t {
handle_type type;
string_t name;
union {
vfs_node_dec *file;
} data;
};
int handle_ids{0};
int available_handles{0};
int set_cycle_id{-1};
int set_resize_id{-1};
std::array<handle_t, HANDLE_NUM> handles;
public:
static struct global_state_t {
bool interrupt{false};
int input_lock{-1};
std::vector<int> input_waiting_list;
std::string input_content;
bool input_success{false};
int input_read_ptr{-1};
string_t hostname{"ccos"};
} global_state;
};
}
#endif //CMINILANG_VM_H