@aptre/v86 0.5.0 → 0.6.1
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 +1113 -93
- package/dist/v86.browser.js.map +4 -4
- package/dist/v86.js +1112 -93
- 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 +53 -23
- package/src/const.ts +2 -0
- package/src/cpu.ts +128 -98
- 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
package/src/virtio.ts
CHANGED
|
@@ -520,18 +520,6 @@ export class VirtIO {
|
|
|
520
520
|
)
|
|
521
521
|
}
|
|
522
522
|
|
|
523
|
-
if (
|
|
524
|
-
data &
|
|
525
|
-
~this.device_status &
|
|
526
|
-
VIRTIO_STATUS_DRIVER_OK &&
|
|
527
|
-
this.device_status &
|
|
528
|
-
VIRTIO_STATUS_DEVICE_NEEDS_RESET
|
|
529
|
-
) {
|
|
530
|
-
// We couldn't notify NEEDS_RESET earlier because DRIVER_OK was not set.
|
|
531
|
-
// Now it has been set, notify now.
|
|
532
|
-
this.notify_config_changes()
|
|
533
|
-
}
|
|
534
|
-
|
|
535
523
|
// Don't set FEATURES_OK if our device doesn't support requested features.
|
|
536
524
|
if (!this.features_ok) {
|
|
537
525
|
if (DEBUG && data & VIRTIO_STATUS_FEATURES_OK) {
|
|
@@ -540,13 +528,17 @@ export class VirtIO {
|
|
|
540
528
|
data &= ~VIRTIO_STATUS_FEATURES_OK
|
|
541
529
|
}
|
|
542
530
|
|
|
531
|
+
const prev_status = this.device_status
|
|
543
532
|
this.device_status = data
|
|
544
533
|
|
|
545
|
-
if (
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
534
|
+
if (data & ~prev_status & VIRTIO_STATUS_DRIVER_OK) {
|
|
535
|
+
if (
|
|
536
|
+
prev_status & VIRTIO_STATUS_DEVICE_NEEDS_RESET
|
|
537
|
+
) {
|
|
538
|
+
// We couldn't notify NEEDS_RESET earlier because DRIVER_OK was not set.
|
|
539
|
+
// Now it has been set, notify now.
|
|
540
|
+
this.notify_config_changes()
|
|
541
|
+
}
|
|
550
542
|
options.on_driver_ok()
|
|
551
543
|
}
|
|
552
544
|
},
|
|
@@ -837,7 +829,7 @@ export class VirtIO {
|
|
|
837
829
|
let cap_next = (this.pci_space[0x34] = 0x40)
|
|
838
830
|
|
|
839
831
|
// Current offset.
|
|
840
|
-
let cap_ptr
|
|
832
|
+
let cap_ptr
|
|
841
833
|
|
|
842
834
|
for (const cap of capabilities) {
|
|
843
835
|
const cap_len = VIRTIO_PCI_CAP_LENGTH + cap.extra.length
|
|
@@ -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
|
+
}
|