@aptre/v86 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/v86.browser.js +1016 -60
- package/dist/v86.browser.js.map +4 -4
- package/dist/v86.js +1015 -60
- package/dist/v86.js.map +4 -4
- package/lib/9p.ts +4 -4
- package/lib/filesystem.ts +1 -1
- package/package.json +7 -7
- package/src/browser/starter.ts +11 -21
- package/src/const.ts +2 -0
- package/src/cpu.ts +48 -8
- package/src/pci.ts +8 -3
- package/src/ps2.ts +2 -2
- package/src/virtio.ts +10 -18
- package/src/virtio_mem.ts +349 -0
- package/src/virtio_v86fs.ts +873 -0
- package/src/rust/gen/analyzer.rs +0 -3807
- package/src/rust/gen/analyzer0f.rs +0 -3992
- package/src/rust/gen/interpreter.rs +0 -4447
- package/src/rust/gen/interpreter0f.rs +0 -5404
- package/src/rust/gen/jit.rs +0 -5080
- package/src/rust/gen/jit0f.rs +0 -5547
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
// https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-4500006
|
|
2
|
+
|
|
3
|
+
import { LOG_PCI } from './const.js'
|
|
4
|
+
import { dbg_log } from './log.js'
|
|
5
|
+
import { VirtIO, VIRTIO_F_VERSION_1 } from './virtio.js'
|
|
6
|
+
import * as _marshall from '../lib/marshall.js'
|
|
7
|
+
import { BusConnector } from './bus.js'
|
|
8
|
+
|
|
9
|
+
interface VirtioMemCPU {
|
|
10
|
+
io: {
|
|
11
|
+
register_read(
|
|
12
|
+
port: number,
|
|
13
|
+
device: object,
|
|
14
|
+
r8?: ((port: number) => number) | undefined,
|
|
15
|
+
r16?: ((port: number) => number) | undefined,
|
|
16
|
+
r32?: ((port: number) => number) | undefined,
|
|
17
|
+
): void
|
|
18
|
+
register_write(
|
|
19
|
+
port: number,
|
|
20
|
+
device: object,
|
|
21
|
+
w8?: ((port: number) => void) | undefined,
|
|
22
|
+
w16?: ((port: number) => void) | undefined,
|
|
23
|
+
w32?: ((port: number) => void) | undefined,
|
|
24
|
+
): void
|
|
25
|
+
}
|
|
26
|
+
devices: {
|
|
27
|
+
pci: {
|
|
28
|
+
register_device(device: VirtIO): void
|
|
29
|
+
raise_irq(pci_id: number): void
|
|
30
|
+
lower_irq(pci_id: number): void
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
read16(addr: number): number
|
|
34
|
+
read32s(addr: number): number
|
|
35
|
+
write16(addr: number, value: number): void
|
|
36
|
+
write32(addr: number, value: number): void
|
|
37
|
+
read_blob(addr: number, length: number): Uint8Array
|
|
38
|
+
write_blob(blob: Uint8Array, addr: number): void
|
|
39
|
+
zero_memory(addr: number, length: number): void
|
|
40
|
+
memory_size: Int32Array
|
|
41
|
+
resize_memory(new_size: number): void
|
|
42
|
+
full_clear_tlb(): void
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Request types
|
|
46
|
+
const VIRTIO_MEM_REQ_PLUG = 0
|
|
47
|
+
const VIRTIO_MEM_REQ_UNPLUG = 1
|
|
48
|
+
const _VIRTIO_MEM_REQ_UNPLUG_ALL = 2
|
|
49
|
+
const VIRTIO_MEM_REQ_STATE = 3
|
|
50
|
+
|
|
51
|
+
// Response types
|
|
52
|
+
const VIRTIO_MEM_RESP_ACK = 0
|
|
53
|
+
const VIRTIO_MEM_RESP_NACK = 1
|
|
54
|
+
const _VIRTIO_MEM_RESP_BUSY = 2
|
|
55
|
+
const VIRTIO_MEM_RESP_ERROR = 3
|
|
56
|
+
|
|
57
|
+
// Default block size: 128MB
|
|
58
|
+
const DEFAULT_BLOCK_SIZE = 128 * 1024 * 1024
|
|
59
|
+
|
|
60
|
+
export class VirtioMem {
|
|
61
|
+
bus: BusConnector
|
|
62
|
+
cpu: VirtioMemCPU
|
|
63
|
+
virtio: VirtIO
|
|
64
|
+
|
|
65
|
+
block_size: number
|
|
66
|
+
region_addr: number
|
|
67
|
+
region_size: number
|
|
68
|
+
usable_region_size: number
|
|
69
|
+
plugged_size: number
|
|
70
|
+
requested_size: number
|
|
71
|
+
|
|
72
|
+
constructor(
|
|
73
|
+
cpu: VirtioMemCPU,
|
|
74
|
+
bus: BusConnector,
|
|
75
|
+
region_addr: number,
|
|
76
|
+
region_size: number,
|
|
77
|
+
block_size?: number,
|
|
78
|
+
) {
|
|
79
|
+
this.bus = bus
|
|
80
|
+
this.cpu = cpu
|
|
81
|
+
this.block_size = block_size || DEFAULT_BLOCK_SIZE
|
|
82
|
+
this.region_addr = region_addr
|
|
83
|
+
this.region_size = region_size
|
|
84
|
+
this.usable_region_size = region_size
|
|
85
|
+
this.plugged_size = 0
|
|
86
|
+
this.requested_size = 0
|
|
87
|
+
|
|
88
|
+
const queues = [{ size_supported: 32, notify_offset: 0 }]
|
|
89
|
+
|
|
90
|
+
this.virtio = new VirtIO(cpu, {
|
|
91
|
+
name: 'virtio-mem',
|
|
92
|
+
pci_id: 0x0d << 3,
|
|
93
|
+
device_id: 0x1058,
|
|
94
|
+
subsystem_device_id: 24,
|
|
95
|
+
common: {
|
|
96
|
+
initial_port: 0xe800,
|
|
97
|
+
queues,
|
|
98
|
+
features: [VIRTIO_F_VERSION_1],
|
|
99
|
+
on_driver_ok: () => {
|
|
100
|
+
dbg_log('virtio-mem setup', LOG_PCI)
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
notification: {
|
|
104
|
+
initial_port: 0xe900,
|
|
105
|
+
single_handler: false,
|
|
106
|
+
handlers: [
|
|
107
|
+
(queue_id: number) => {
|
|
108
|
+
this.handle_request(queue_id)
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
isr_status: {
|
|
113
|
+
initial_port: 0xe700,
|
|
114
|
+
},
|
|
115
|
+
device_specific: {
|
|
116
|
+
initial_port: 0xe600,
|
|
117
|
+
struct: [
|
|
118
|
+
// block_size low
|
|
119
|
+
{
|
|
120
|
+
bytes: 4,
|
|
121
|
+
name: 'block_size_low',
|
|
122
|
+
read: () => this.block_size >>> 0,
|
|
123
|
+
write: () => {},
|
|
124
|
+
},
|
|
125
|
+
// block_size high
|
|
126
|
+
{
|
|
127
|
+
bytes: 4,
|
|
128
|
+
name: 'block_size_high',
|
|
129
|
+
read: () => 0,
|
|
130
|
+
write: () => {},
|
|
131
|
+
},
|
|
132
|
+
// node_id (u16 padded to u32)
|
|
133
|
+
{
|
|
134
|
+
bytes: 2,
|
|
135
|
+
name: 'node_id',
|
|
136
|
+
read: () => 0,
|
|
137
|
+
write: () => {},
|
|
138
|
+
},
|
|
139
|
+
// padding (6 bytes as 2+4)
|
|
140
|
+
{
|
|
141
|
+
bytes: 2,
|
|
142
|
+
name: 'padding0',
|
|
143
|
+
read: () => 0,
|
|
144
|
+
write: () => {},
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
bytes: 4,
|
|
148
|
+
name: 'padding1',
|
|
149
|
+
read: () => 0,
|
|
150
|
+
write: () => {},
|
|
151
|
+
},
|
|
152
|
+
// addr low
|
|
153
|
+
{
|
|
154
|
+
bytes: 4,
|
|
155
|
+
name: 'addr_low',
|
|
156
|
+
read: () => this.region_addr >>> 0,
|
|
157
|
+
write: () => {},
|
|
158
|
+
},
|
|
159
|
+
// addr high
|
|
160
|
+
{
|
|
161
|
+
bytes: 4,
|
|
162
|
+
name: 'addr_high',
|
|
163
|
+
read: () => 0,
|
|
164
|
+
write: () => {},
|
|
165
|
+
},
|
|
166
|
+
// region_size low
|
|
167
|
+
{
|
|
168
|
+
bytes: 4,
|
|
169
|
+
name: 'region_size_low',
|
|
170
|
+
read: () => this.region_size >>> 0,
|
|
171
|
+
write: () => {},
|
|
172
|
+
},
|
|
173
|
+
// region_size high
|
|
174
|
+
{
|
|
175
|
+
bytes: 4,
|
|
176
|
+
name: 'region_size_high',
|
|
177
|
+
read: () => 0,
|
|
178
|
+
write: () => {},
|
|
179
|
+
},
|
|
180
|
+
// usable_region_size low
|
|
181
|
+
{
|
|
182
|
+
bytes: 4,
|
|
183
|
+
name: 'usable_region_size_low',
|
|
184
|
+
read: () => this.usable_region_size >>> 0,
|
|
185
|
+
write: () => {},
|
|
186
|
+
},
|
|
187
|
+
// usable_region_size high
|
|
188
|
+
{
|
|
189
|
+
bytes: 4,
|
|
190
|
+
name: 'usable_region_size_high',
|
|
191
|
+
read: () => 0,
|
|
192
|
+
write: () => {},
|
|
193
|
+
},
|
|
194
|
+
// plugged_size low
|
|
195
|
+
{
|
|
196
|
+
bytes: 4,
|
|
197
|
+
name: 'plugged_size_low',
|
|
198
|
+
read: () => this.plugged_size >>> 0,
|
|
199
|
+
write: () => {},
|
|
200
|
+
},
|
|
201
|
+
// plugged_size high
|
|
202
|
+
{
|
|
203
|
+
bytes: 4,
|
|
204
|
+
name: 'plugged_size_high',
|
|
205
|
+
read: () => 0,
|
|
206
|
+
write: () => {},
|
|
207
|
+
},
|
|
208
|
+
// requested_size low
|
|
209
|
+
{
|
|
210
|
+
bytes: 4,
|
|
211
|
+
name: 'requested_size_low',
|
|
212
|
+
read: () => this.requested_size >>> 0,
|
|
213
|
+
write: () => {},
|
|
214
|
+
},
|
|
215
|
+
// requested_size high
|
|
216
|
+
{
|
|
217
|
+
bytes: 4,
|
|
218
|
+
name: 'requested_size_high',
|
|
219
|
+
read: () => 0,
|
|
220
|
+
write: () => {},
|
|
221
|
+
},
|
|
222
|
+
],
|
|
223
|
+
},
|
|
224
|
+
})
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
handle_request(queue_id: number): void {
|
|
228
|
+
const queue = this.virtio.queues[queue_id]
|
|
229
|
+
while (queue.has_request()) {
|
|
230
|
+
const bufchain = queue.pop_request()
|
|
231
|
+
const request = new Uint8Array(bufchain.length_readable)
|
|
232
|
+
bufchain.get_next_blob(request)
|
|
233
|
+
|
|
234
|
+
const type = request[0] | (request[1] << 8)
|
|
235
|
+
const resp = new Uint8Array(8)
|
|
236
|
+
|
|
237
|
+
let resp_type = VIRTIO_MEM_RESP_ERROR
|
|
238
|
+
switch (type) {
|
|
239
|
+
case VIRTIO_MEM_REQ_PLUG:
|
|
240
|
+
resp_type = this.handle_plug(request)
|
|
241
|
+
break
|
|
242
|
+
case VIRTIO_MEM_REQ_UNPLUG:
|
|
243
|
+
resp_type = VIRTIO_MEM_RESP_NACK
|
|
244
|
+
break
|
|
245
|
+
case VIRTIO_MEM_REQ_STATE:
|
|
246
|
+
resp_type = this.handle_state(request, resp)
|
|
247
|
+
break
|
|
248
|
+
default:
|
|
249
|
+
dbg_log('virtio-mem: unknown request type ' + type, LOG_PCI)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
resp[0] = resp_type & 0xff
|
|
253
|
+
resp[1] = (resp_type >> 8) & 0xff
|
|
254
|
+
|
|
255
|
+
bufchain.set_next_blob(resp)
|
|
256
|
+
queue.push_reply(bufchain)
|
|
257
|
+
}
|
|
258
|
+
queue.flush_replies()
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
handle_plug(request: Uint8Array): number {
|
|
262
|
+
// Request layout after type (8 bytes header):
|
|
263
|
+
// addr: u64 at offset 8
|
|
264
|
+
// nb_blocks: u16 at offset 16
|
|
265
|
+
const addr =
|
|
266
|
+
(request[8] |
|
|
267
|
+
(request[9] << 8) |
|
|
268
|
+
(request[10] << 16) |
|
|
269
|
+
(request[11] << 24)) >>>
|
|
270
|
+
0
|
|
271
|
+
const nb_blocks = request[16] | (request[17] << 8)
|
|
272
|
+
|
|
273
|
+
const size = nb_blocks * this.block_size
|
|
274
|
+
const new_plugged = this.plugged_size + size
|
|
275
|
+
|
|
276
|
+
if (new_plugged > this.usable_region_size) {
|
|
277
|
+
return VIRTIO_MEM_RESP_NACK
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Grow guest memory to accommodate the plug
|
|
281
|
+
const new_memory_size = this.cpu.memory_size[0] + size
|
|
282
|
+
this.cpu.resize_memory(new_memory_size)
|
|
283
|
+
this.cpu.full_clear_tlb()
|
|
284
|
+
this.plugged_size = new_plugged
|
|
285
|
+
|
|
286
|
+
dbg_log(
|
|
287
|
+
'virtio-mem: plugged ' +
|
|
288
|
+
nb_blocks +
|
|
289
|
+
' blocks at 0x' +
|
|
290
|
+
addr.toString(16) +
|
|
291
|
+
' (' +
|
|
292
|
+
(size >> 20) +
|
|
293
|
+
'MB)',
|
|
294
|
+
LOG_PCI,
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
return VIRTIO_MEM_RESP_ACK
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
handle_state(request: Uint8Array, resp: Uint8Array): number {
|
|
301
|
+
const addr =
|
|
302
|
+
(request[8] |
|
|
303
|
+
(request[9] << 8) |
|
|
304
|
+
(request[10] << 16) |
|
|
305
|
+
(request[11] << 24)) >>>
|
|
306
|
+
0
|
|
307
|
+
const nb_blocks = request[16] | (request[17] << 8)
|
|
308
|
+
|
|
309
|
+
// Report all requested blocks as plugged if within plugged_size
|
|
310
|
+
const offset = addr - this.region_addr
|
|
311
|
+
const end = offset + nb_blocks * this.block_size
|
|
312
|
+
const all_plugged = end <= this.plugged_size ? 1 : 0
|
|
313
|
+
|
|
314
|
+
// State response: count field at offset 8
|
|
315
|
+
resp[8] = all_plugged & 0xff
|
|
316
|
+
resp[9] = (all_plugged >> 8) & 0xff
|
|
317
|
+
|
|
318
|
+
return VIRTIO_MEM_RESP_ACK
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
set_requested_size(size: number): void {
|
|
322
|
+
this.requested_size = size
|
|
323
|
+
if (this.virtio.device_status & 4) {
|
|
324
|
+
this.virtio.notify_config_changes()
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
get_state(): any[] {
|
|
329
|
+
const state: any[] = []
|
|
330
|
+
state[0] = this.virtio
|
|
331
|
+
state[1] = this.block_size
|
|
332
|
+
state[2] = this.region_addr
|
|
333
|
+
state[3] = this.region_size
|
|
334
|
+
state[4] = this.usable_region_size
|
|
335
|
+
state[5] = this.plugged_size
|
|
336
|
+
state[6] = this.requested_size
|
|
337
|
+
return state
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
set_state(state: any[]): void {
|
|
341
|
+
this.virtio.set_state(state[0])
|
|
342
|
+
this.block_size = state[1]
|
|
343
|
+
this.region_addr = state[2]
|
|
344
|
+
this.region_size = state[3]
|
|
345
|
+
this.usable_region_size = state[4]
|
|
346
|
+
this.plugged_size = state[5]
|
|
347
|
+
this.requested_size = state[6]
|
|
348
|
+
}
|
|
349
|
+
}
|