@aptre/v86 0.5.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.
Files changed (111) hide show
  1. package/LICENSE +22 -0
  2. package/LICENSE.MIT +22 -0
  3. package/Readme.md +237 -0
  4. package/dist/v86.browser.js +26666 -0
  5. package/dist/v86.browser.js.map +7 -0
  6. package/dist/v86.js +26632 -0
  7. package/dist/v86.js.map +7 -0
  8. package/gen/generate_analyzer.ts +512 -0
  9. package/gen/generate_interpreter.ts +522 -0
  10. package/gen/generate_jit.ts +624 -0
  11. package/gen/rust_ast.ts +107 -0
  12. package/gen/util.ts +35 -0
  13. package/gen/x86_table.ts +1836 -0
  14. package/lib/9p.ts +1547 -0
  15. package/lib/filesystem.ts +1879 -0
  16. package/lib/marshall.ts +168 -0
  17. package/lib/softfloat/softfloat.c +32501 -0
  18. package/lib/zstd/zstddeclib.c +13520 -0
  19. package/package.json +75 -0
  20. package/src/acpi.ts +267 -0
  21. package/src/browser/dummy_screen.ts +106 -0
  22. package/src/browser/fake_network.ts +1771 -0
  23. package/src/browser/fetch_network.ts +361 -0
  24. package/src/browser/filestorage.ts +124 -0
  25. package/src/browser/inbrowser_network.ts +57 -0
  26. package/src/browser/keyboard.ts +564 -0
  27. package/src/browser/main.ts +3415 -0
  28. package/src/browser/mouse.ts +255 -0
  29. package/src/browser/network.ts +142 -0
  30. package/src/browser/print_stats.ts +336 -0
  31. package/src/browser/screen.ts +978 -0
  32. package/src/browser/serial.ts +316 -0
  33. package/src/browser/speaker.ts +1223 -0
  34. package/src/browser/starter.ts +1688 -0
  35. package/src/browser/wisp_network.ts +332 -0
  36. package/src/browser/worker_bus.ts +64 -0
  37. package/src/buffer.ts +652 -0
  38. package/src/bus.ts +78 -0
  39. package/src/const.ts +128 -0
  40. package/src/cpu.ts +2891 -0
  41. package/src/dma.ts +474 -0
  42. package/src/elf.ts +251 -0
  43. package/src/floppy.ts +1778 -0
  44. package/src/ide.ts +3455 -0
  45. package/src/io.ts +504 -0
  46. package/src/iso9660.ts +317 -0
  47. package/src/kernel.ts +250 -0
  48. package/src/lib.ts +645 -0
  49. package/src/log.ts +149 -0
  50. package/src/main.ts +199 -0
  51. package/src/ne2k.ts +1589 -0
  52. package/src/pci.ts +815 -0
  53. package/src/pit.ts +406 -0
  54. package/src/ps2.ts +820 -0
  55. package/src/rtc.ts +537 -0
  56. package/src/rust/analysis.rs +101 -0
  57. package/src/rust/codegen.rs +2660 -0
  58. package/src/rust/config.rs +3 -0
  59. package/src/rust/control_flow.rs +425 -0
  60. package/src/rust/cpu/apic.rs +658 -0
  61. package/src/rust/cpu/arith.rs +1207 -0
  62. package/src/rust/cpu/call_indirect.rs +2 -0
  63. package/src/rust/cpu/cpu.rs +4501 -0
  64. package/src/rust/cpu/fpu.rs +923 -0
  65. package/src/rust/cpu/global_pointers.rs +112 -0
  66. package/src/rust/cpu/instructions.rs +2486 -0
  67. package/src/rust/cpu/instructions_0f.rs +5261 -0
  68. package/src/rust/cpu/ioapic.rs +316 -0
  69. package/src/rust/cpu/memory.rs +351 -0
  70. package/src/rust/cpu/misc_instr.rs +613 -0
  71. package/src/rust/cpu/mod.rs +16 -0
  72. package/src/rust/cpu/modrm.rs +133 -0
  73. package/src/rust/cpu/pic.rs +402 -0
  74. package/src/rust/cpu/sse_instr.rs +361 -0
  75. package/src/rust/cpu/string.rs +701 -0
  76. package/src/rust/cpu/vga.rs +175 -0
  77. package/src/rust/cpu_context.rs +69 -0
  78. package/src/rust/dbg.rs +98 -0
  79. package/src/rust/gen/analyzer.rs +3807 -0
  80. package/src/rust/gen/analyzer0f.rs +3992 -0
  81. package/src/rust/gen/interpreter.rs +4447 -0
  82. package/src/rust/gen/interpreter0f.rs +5404 -0
  83. package/src/rust/gen/jit.rs +5080 -0
  84. package/src/rust/gen/jit0f.rs +5547 -0
  85. package/src/rust/gen/mod.rs +14 -0
  86. package/src/rust/jit.rs +2443 -0
  87. package/src/rust/jit_instructions.rs +7881 -0
  88. package/src/rust/js_api.rs +6 -0
  89. package/src/rust/leb.rs +46 -0
  90. package/src/rust/lib.rs +29 -0
  91. package/src/rust/modrm.rs +330 -0
  92. package/src/rust/opstats.rs +249 -0
  93. package/src/rust/page.rs +15 -0
  94. package/src/rust/paging.rs +25 -0
  95. package/src/rust/prefix.rs +15 -0
  96. package/src/rust/profiler.rs +155 -0
  97. package/src/rust/regs.rs +38 -0
  98. package/src/rust/softfloat.rs +286 -0
  99. package/src/rust/state_flags.rs +27 -0
  100. package/src/rust/wasmgen/mod.rs +2 -0
  101. package/src/rust/wasmgen/wasm_builder.rs +1047 -0
  102. package/src/rust/wasmgen/wasm_opcodes.rs +221 -0
  103. package/src/rust/zstd.rs +105 -0
  104. package/src/sb16.ts +1928 -0
  105. package/src/state.ts +359 -0
  106. package/src/uart.ts +472 -0
  107. package/src/vga.ts +2791 -0
  108. package/src/virtio.ts +1756 -0
  109. package/src/virtio_balloon.ts +273 -0
  110. package/src/virtio_console.ts +372 -0
  111. package/src/virtio_net.ts +326 -0
@@ -0,0 +1,316 @@
1
+ // http://download.intel.com/design/chipsets/datashts/29056601.pdf
2
+
3
+ use crate::cpu::{apic, global_pointers::acpi_enabled};
4
+ use std::sync::{Mutex, MutexGuard};
5
+
6
+ const IOAPIC_LOG_VERBOSE: bool = false;
7
+
8
+ const IOREGSEL: u32 = 0;
9
+ const IOWIN: u32 = 0x10;
10
+
11
+ const IOAPIC_IRQ_COUNT: usize = 24;
12
+
13
+ const IOAPIC_FIRST_IRQ_REG: u32 = 0x10;
14
+ const IOAPIC_LAST_IRQ_REG: u32 = 0x10 + 2 * IOAPIC_IRQ_COUNT as u32;
15
+
16
+ const IOAPIC_ID: u32 = 0; // must match value in seabios
17
+
18
+ pub const IOAPIC_CONFIG_TRIGGER_MODE_LEVEL: u32 = 1 << 15;
19
+
20
+ const IOAPIC_CONFIG_MASKED: u32 = 1 << 16;
21
+ const IOAPIC_CONFIG_DELIVS: u32 = 1 << 12;
22
+ const IOAPIC_CONFIG_REMOTE_IRR: u32 = 1 << 14;
23
+ const IOAPIC_CONFIG_READONLY_MASK: u32 =
24
+ IOAPIC_CONFIG_REMOTE_IRR | IOAPIC_CONFIG_DELIVS | 0xFFFE0000;
25
+
26
+ const IOAPIC_DELIVERY_FIXED: u8 = 0;
27
+ const IOAPIC_DELIVERY_LOWEST_PRIORITY: u8 = 1;
28
+ const _IOAPIC_DELIVERY_NMI: u8 = 4;
29
+ const _IOAPIC_DELIVERY_INIT: u8 = 5;
30
+
31
+ const DELIVERY_MODES: [&str; 8] = [
32
+ "Fixed (0)",
33
+ "Lowest Prio (1)",
34
+ "SMI (2)",
35
+ "Reserved (3)",
36
+ "NMI (4)",
37
+ "INIT (5)",
38
+ "Reserved (6)",
39
+ "ExtINT (7)",
40
+ ];
41
+
42
+ const DESTINATION_MODES: [&str; 2] = ["physical", "logical"];
43
+
44
+ // keep in sync with cpu.js
45
+ #[allow(dead_code)]
46
+ const IOAPIC_STRUCT_SIZE: usize = 4 * 52;
47
+
48
+ // Note: JavaScript (cpu.get_state_apic) depens on this layout
49
+ const _: () = assert!(std::mem::offset_of!(Ioapic, ioredtbl_destination) == 24 * 4);
50
+ const _: () = assert!(std::mem::offset_of!(Ioapic, ioregsel) == 48 * 4);
51
+ const _: () = assert!(std::mem::offset_of!(Ioapic, irq_value) == 51 * 4);
52
+ const _: () = assert!(std::mem::size_of::<Ioapic>() == IOAPIC_STRUCT_SIZE);
53
+ #[repr(C)]
54
+ struct Ioapic {
55
+ ioredtbl_config: [u32; IOAPIC_IRQ_COUNT],
56
+ ioredtbl_destination: [u32; IOAPIC_IRQ_COUNT],
57
+ ioregsel: u32,
58
+ ioapic_id: u32,
59
+ irr: u32,
60
+ irq_value: u32,
61
+ }
62
+
63
+ static IOAPIC: Mutex<Ioapic> = Mutex::new(Ioapic {
64
+ ioredtbl_config: [IOAPIC_CONFIG_MASKED; IOAPIC_IRQ_COUNT],
65
+ ioredtbl_destination: [0; IOAPIC_IRQ_COUNT],
66
+ ioregsel: 0,
67
+ ioapic_id: IOAPIC_ID,
68
+ irr: 0,
69
+ irq_value: 0,
70
+ });
71
+
72
+ fn get_ioapic() -> MutexGuard<'static, Ioapic> { IOAPIC.try_lock().unwrap() }
73
+
74
+ #[no_mangle]
75
+ pub fn get_ioapic_addr() -> u32 { &raw mut *get_ioapic() as u32 }
76
+
77
+ pub fn remote_eoi(apic: &mut apic::Apic, vector: u8) {
78
+ remote_eoi_internal(&mut get_ioapic(), apic, vector);
79
+ }
80
+
81
+ fn remote_eoi_internal(ioapic: &mut Ioapic, apic: &mut apic::Apic, vector: u8) {
82
+ for i in 0..IOAPIC_IRQ_COUNT as u8 {
83
+ let config = ioapic.ioredtbl_config[i as usize];
84
+
85
+ if (config & 0xFF) as u8 == vector && config & IOAPIC_CONFIG_REMOTE_IRR != 0 {
86
+ dbg_log!("Clear remote IRR for irq={:x}", i);
87
+ ioapic.ioredtbl_config[i as usize] &= !IOAPIC_CONFIG_REMOTE_IRR;
88
+ check_irq(ioapic, apic, i);
89
+ }
90
+ }
91
+ }
92
+
93
+ fn check_irq(ioapic: &mut Ioapic, apic: &mut apic::Apic, irq: u8) {
94
+ let mask = 1 << irq;
95
+
96
+ if ioapic.irr & mask == 0 {
97
+ return;
98
+ }
99
+
100
+ let config = ioapic.ioredtbl_config[irq as usize];
101
+
102
+ if config & IOAPIC_CONFIG_MASKED == 0 {
103
+ let delivery_mode = ((config >> 8) & 7) as u8;
104
+ let destination_mode = ((config >> 11) & 1) as u8;
105
+ let vector = (config & 0xFF) as u8;
106
+ let destination = (ioapic.ioredtbl_destination[irq as usize] >> 24) as u8;
107
+ let is_level =
108
+ config & IOAPIC_CONFIG_TRIGGER_MODE_LEVEL == IOAPIC_CONFIG_TRIGGER_MODE_LEVEL;
109
+
110
+ if config & IOAPIC_CONFIG_TRIGGER_MODE_LEVEL == 0 {
111
+ ioapic.irr &= !mask;
112
+ }
113
+ else {
114
+ ioapic.ioredtbl_config[irq as usize] |= IOAPIC_CONFIG_REMOTE_IRR;
115
+
116
+ if config & IOAPIC_CONFIG_REMOTE_IRR != 0 {
117
+ dbg_log!("No route: level interrupt and remote IRR still set");
118
+ return;
119
+ }
120
+ }
121
+
122
+ if delivery_mode == IOAPIC_DELIVERY_FIXED
123
+ || delivery_mode == IOAPIC_DELIVERY_LOWEST_PRIORITY
124
+ {
125
+ apic::route(
126
+ apic,
127
+ vector,
128
+ delivery_mode,
129
+ is_level,
130
+ destination,
131
+ destination_mode,
132
+ );
133
+ }
134
+ else {
135
+ dbg_assert!(false, "TODO");
136
+ }
137
+
138
+ ioapic.ioredtbl_config[irq as usize] &= !IOAPIC_CONFIG_DELIVS;
139
+ }
140
+ }
141
+
142
+ pub fn set_irq(i: u8) { set_irq_internal(&mut get_ioapic(), &mut apic::get_apic(), i) }
143
+
144
+ fn set_irq_internal(ioapic: &mut Ioapic, apic: &mut apic::Apic, i: u8) {
145
+ if i as usize >= IOAPIC_IRQ_COUNT {
146
+ dbg_assert!(false, "Bad irq: {}", i);
147
+ return;
148
+ }
149
+
150
+ let mask = 1 << i;
151
+
152
+ if ioapic.irq_value & mask == 0 {
153
+ if IOAPIC_LOG_VERBOSE {
154
+ dbg_log!("apic set irq {}", i);
155
+ }
156
+
157
+ ioapic.irq_value |= mask;
158
+
159
+ let config = ioapic.ioredtbl_config[i as usize];
160
+ if config & (IOAPIC_CONFIG_TRIGGER_MODE_LEVEL | IOAPIC_CONFIG_MASKED)
161
+ == IOAPIC_CONFIG_MASKED
162
+ {
163
+ // edge triggered and masked
164
+ return;
165
+ }
166
+
167
+ ioapic.irr |= mask;
168
+
169
+ check_irq(ioapic, apic, i);
170
+ }
171
+ }
172
+
173
+ pub fn clear_irq(i: u8) { clear_irq_internal(&mut get_ioapic(), i) }
174
+
175
+ fn clear_irq_internal(ioapic: &mut Ioapic, i: u8) {
176
+ if i as usize >= IOAPIC_IRQ_COUNT {
177
+ dbg_assert!(false, "Bad irq: {}", i);
178
+ return;
179
+ }
180
+
181
+ let mask = 1 << i;
182
+
183
+ if ioapic.irq_value & mask == mask {
184
+ ioapic.irq_value &= !mask;
185
+
186
+ let config = ioapic.ioredtbl_config[i as usize];
187
+ if config & IOAPIC_CONFIG_TRIGGER_MODE_LEVEL != 0 {
188
+ ioapic.irr &= !mask;
189
+ }
190
+ }
191
+ }
192
+
193
+ pub fn read32(addr: u32) -> u32 {
194
+ if unsafe { !*acpi_enabled } {
195
+ return 0;
196
+ }
197
+ read32_internal(&mut get_ioapic(), addr)
198
+ }
199
+
200
+ fn read32_internal(ioapic: &mut Ioapic, addr: u32) -> u32 {
201
+ match addr {
202
+ IOREGSEL => ioapic.ioregsel,
203
+ IOWIN => match ioapic.ioregsel {
204
+ 0 => {
205
+ dbg_log!("IOAPIC Read id");
206
+ ioapic.ioapic_id << 24
207
+ },
208
+ 1 => {
209
+ dbg_log!("IOAPIC Read version");
210
+ 0x11 | (IOAPIC_IRQ_COUNT as u32 - 1) << 16
211
+ },
212
+ 2 => {
213
+ dbg_log!("IOAPIC Read arbitration id");
214
+ ioapic.ioapic_id << 24
215
+ },
216
+ IOAPIC_FIRST_IRQ_REG..IOAPIC_LAST_IRQ_REG => {
217
+ let irq = ((ioapic.ioregsel - IOAPIC_FIRST_IRQ_REG) >> 1) as u8;
218
+ let index = ioapic.ioregsel & 1;
219
+
220
+ if index != 0 {
221
+ let value = ioapic.ioredtbl_destination[irq as usize];
222
+ dbg_log!("IOAPIC Read destination irq={:x} -> {:08x}", irq, value);
223
+ value
224
+ }
225
+ else {
226
+ let value = ioapic.ioredtbl_config[irq as usize];
227
+ dbg_log!("IOAPIC Read config irq={:x} -> {:08x}", irq, value);
228
+ value
229
+ }
230
+ },
231
+ reg => {
232
+ dbg_assert!(false, "IOAPIC register read outside of range {:x}", reg);
233
+ 0
234
+ },
235
+ },
236
+ _ => {
237
+ dbg_assert!(false, "Unaligned or oob IOAPIC memory read: {:x}", addr);
238
+ 0
239
+ },
240
+ }
241
+ }
242
+
243
+ pub fn write32(addr: u32, value: u32) {
244
+ if unsafe { !*acpi_enabled } {
245
+ return;
246
+ }
247
+ write32_internal(&mut get_ioapic(), &mut apic::get_apic(), addr, value)
248
+ }
249
+
250
+ fn write32_internal(ioapic: &mut Ioapic, apic: &mut apic::Apic, addr: u32, value: u32) {
251
+ //dbg_log!("IOAPIC write {:x} <- {:08x}", reg, value);
252
+
253
+ match addr {
254
+ IOREGSEL => ioapic.ioregsel = value,
255
+ IOWIN => match ioapic.ioregsel {
256
+ 0 => ioapic.ioapic_id = (value >> 24) & 0x0F,
257
+ 1 | 2 => {
258
+ dbg_log!("IOAPIC Invalid write: {}", ioapic.ioregsel);
259
+ },
260
+ IOAPIC_FIRST_IRQ_REG..IOAPIC_LAST_IRQ_REG => {
261
+ let irq = ((ioapic.ioregsel - IOAPIC_FIRST_IRQ_REG) >> 1) as u8;
262
+ let index = ioapic.ioregsel & 1;
263
+
264
+ if index != 0 {
265
+ dbg_log!(
266
+ "Write destination {:08x} irq={:x} dest={:02x}",
267
+ value,
268
+ irq,
269
+ value >> 24
270
+ );
271
+ ioapic.ioredtbl_destination[irq as usize] = value & 0xFF000000;
272
+ }
273
+ else {
274
+ let old_value = ioapic.ioredtbl_config[irq as usize] as u32;
275
+ ioapic.ioredtbl_config[irq as usize] = (value & !IOAPIC_CONFIG_READONLY_MASK)
276
+ | (old_value & IOAPIC_CONFIG_READONLY_MASK);
277
+
278
+ let vector = value & 0xFF;
279
+ let delivery_mode = (value >> 8) & 7;
280
+ let destination_mode = (value >> 11) & 1;
281
+ let is_level = (value >> 15) & 1;
282
+ let disabled = (value >> 16) & 1;
283
+
284
+ dbg_log!(
285
+ "Write config {:08x} irq={:x} vector={:02x} deliverymode={} destmode={} is_level={} disabled={}",
286
+ value,
287
+ irq,
288
+ vector,
289
+ DELIVERY_MODES[delivery_mode as usize],
290
+ DESTINATION_MODES[destination_mode as usize],
291
+ is_level,
292
+ disabled
293
+ );
294
+
295
+ check_irq(ioapic, apic, irq);
296
+ }
297
+ },
298
+ reg => {
299
+ dbg_assert!(
300
+ false,
301
+ "IOAPIC register write outside of range {:x} <- {:x}",
302
+ reg,
303
+ value
304
+ )
305
+ },
306
+ },
307
+ _ => {
308
+ dbg_assert!(
309
+ false,
310
+ "Unaligned or oob IOAPIC memory write: {:x} <- {:x}",
311
+ addr,
312
+ value
313
+ )
314
+ },
315
+ }
316
+ }
@@ -0,0 +1,351 @@
1
+ mod ext {
2
+ extern "C" {
3
+ pub fn mmap_read8(addr: u32) -> i32;
4
+ pub fn mmap_read32(addr: u32) -> i32;
5
+
6
+ pub fn mmap_write8(addr: u32, value: i32);
7
+ pub fn mmap_write16(addr: u32, value: i32);
8
+ pub fn mmap_write32(addr: u32, value: i32);
9
+ pub fn mmap_write64(addr: u32, v0: i32, v1: i32);
10
+ pub fn mmap_write128(addr: u32, v0: i32, v1: i32, v2: i32, v3: i32);
11
+ }
12
+ }
13
+
14
+ use crate::cpu::apic;
15
+ use crate::cpu::cpu::{
16
+ handle_irqs, reg128, APIC_MEM_ADDRESS, APIC_MEM_SIZE, IOAPIC_MEM_ADDRESS, IOAPIC_MEM_SIZE,
17
+ };
18
+ use crate::cpu::global_pointers::memory_size;
19
+ use crate::cpu::ioapic;
20
+ use crate::cpu::vga;
21
+ use crate::jit;
22
+ use crate::page::Page;
23
+
24
+ use std::alloc;
25
+ use std::ptr;
26
+
27
+ #[allow(non_upper_case_globals)]
28
+ pub static mut mem8: *mut u8 = ptr::null_mut();
29
+
30
+ #[no_mangle]
31
+ pub fn allocate_memory(size: u32) -> u32 {
32
+ unsafe {
33
+ dbg_assert!(mem8.is_null());
34
+ };
35
+ dbg_log!("Allocate memory size={}m", size >> 20);
36
+ let layout = alloc::Layout::from_size_align(size as usize, 0x1000).unwrap();
37
+ let ptr = unsafe { alloc::alloc(layout) as u32 };
38
+ unsafe {
39
+ mem8 = ptr as *mut u8;
40
+ };
41
+ ptr
42
+ }
43
+
44
+ #[no_mangle]
45
+ pub unsafe fn zero_memory(addr: u32, size: u32) {
46
+ ptr::write_bytes(mem8.offset(addr as isize), 0, size as usize);
47
+ }
48
+
49
+ #[allow(non_upper_case_globals)]
50
+ pub static mut vga_mem8: *mut u8 = ptr::null_mut();
51
+ #[allow(non_upper_case_globals)]
52
+ pub static mut vga_memory_size: u32 = 0;
53
+
54
+ #[no_mangle]
55
+ pub fn svga_allocate_memory(size: u32) -> u32 {
56
+ unsafe {
57
+ dbg_assert!(vga_mem8.is_null());
58
+ };
59
+ let layout = alloc::Layout::from_size_align(size as usize, 0x1000).unwrap();
60
+ let ptr = unsafe { alloc::alloc(layout) };
61
+ dbg_assert!(
62
+ size & (1 << 12 << 6) == 0,
63
+ "size not aligned to dirty_bitmap"
64
+ );
65
+ unsafe {
66
+ vga_mem8 = ptr;
67
+ vga_memory_size = size;
68
+ vga::set_dirty_bitmap_size(size >> 12 >> 6);
69
+ };
70
+ ptr as u32
71
+ }
72
+
73
+ #[no_mangle]
74
+ pub fn in_mapped_range(addr: u32) -> bool {
75
+ return addr >= 0xA0000 && addr < 0xC0000 || addr >= unsafe { *memory_size };
76
+ }
77
+
78
+ pub const VGA_LFB_ADDRESS: u32 = 0xE0000000;
79
+ pub fn in_svga_lfb(addr: u32) -> bool {
80
+ addr >= VGA_LFB_ADDRESS && addr <= unsafe { VGA_LFB_ADDRESS + (vga_memory_size - 1) }
81
+ }
82
+
83
+ #[no_mangle]
84
+ pub fn read8(addr: u32) -> i32 {
85
+ if in_mapped_range(addr) {
86
+ if in_svga_lfb(addr) {
87
+ unsafe { *vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as i32 }
88
+ }
89
+ else if addr >= APIC_MEM_ADDRESS && addr < APIC_MEM_ADDRESS + APIC_MEM_SIZE {
90
+ apic::read32((addr - APIC_MEM_ADDRESS) & !3) as i32 >> 8 * (addr & 3) & 0xFF
91
+ }
92
+ else if addr >= IOAPIC_MEM_ADDRESS && addr < IOAPIC_MEM_ADDRESS + IOAPIC_MEM_SIZE {
93
+ ioapic::read32((addr - IOAPIC_MEM_ADDRESS) & !3) as i32 >> 8 * (addr & 3) & 0xFF
94
+ }
95
+ else {
96
+ unsafe { ext::mmap_read8(addr) }
97
+ }
98
+ }
99
+ else {
100
+ read8_no_mmap_check(addr)
101
+ }
102
+ }
103
+ pub fn read8_no_mmap_check(addr: u32) -> i32 { unsafe { *mem8.offset(addr as isize) as i32 } }
104
+
105
+ #[no_mangle]
106
+ pub fn read16(addr: u32) -> i32 {
107
+ if in_mapped_range(addr) {
108
+ if in_svga_lfb(addr) {
109
+ unsafe {
110
+ ptr::read_unaligned(vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *const u16)
111
+ as i32
112
+ }
113
+ }
114
+ else {
115
+ read8(addr) | read8(addr + 1) << 8
116
+ }
117
+ }
118
+ else {
119
+ read16_no_mmap_check(addr)
120
+ }
121
+ }
122
+ pub fn read16_no_mmap_check(addr: u32) -> i32 {
123
+ unsafe { ptr::read_unaligned(mem8.offset(addr as isize) as *const u16) as i32 }
124
+ }
125
+
126
+ #[no_mangle]
127
+ pub fn read32s(addr: u32) -> i32 {
128
+ if in_mapped_range(addr) {
129
+ if in_svga_lfb(addr) {
130
+ unsafe {
131
+ ptr::read_unaligned(vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *const i32)
132
+ } // XXX
133
+ }
134
+ else if addr >= APIC_MEM_ADDRESS && addr < APIC_MEM_ADDRESS + APIC_MEM_SIZE {
135
+ apic::read32(addr - APIC_MEM_ADDRESS) as i32
136
+ }
137
+ else if addr >= IOAPIC_MEM_ADDRESS && addr < IOAPIC_MEM_ADDRESS + IOAPIC_MEM_SIZE {
138
+ ioapic::read32(addr - IOAPIC_MEM_ADDRESS) as i32
139
+ }
140
+ else {
141
+ unsafe { ext::mmap_read32(addr) }
142
+ }
143
+ }
144
+ else {
145
+ read32_no_mmap_check(addr)
146
+ }
147
+ }
148
+ pub fn read32_no_mmap_check(addr: u32) -> i32 {
149
+ unsafe { ptr::read_unaligned(mem8.offset(addr as isize) as *const i32) }
150
+ }
151
+
152
+ pub unsafe fn read64s(addr: u32) -> i64 {
153
+ if in_mapped_range(addr) {
154
+ if in_svga_lfb(addr) {
155
+ ptr::read_unaligned(vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *const i64)
156
+ }
157
+ else {
158
+ read32s(addr) as i64 | (read32s(addr + 4) as i64) << 32
159
+ }
160
+ }
161
+ else {
162
+ ptr::read_unaligned(mem8.offset(addr as isize) as *const i64)
163
+ }
164
+ }
165
+
166
+ pub unsafe fn read128(addr: u32) -> reg128 {
167
+ if in_mapped_range(addr) {
168
+ if in_svga_lfb(addr) {
169
+ ptr::read_unaligned(vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *const reg128)
170
+ }
171
+ else {
172
+ reg128 {
173
+ i32: [
174
+ read32s(addr + 0),
175
+ read32s(addr + 4),
176
+ read32s(addr + 8),
177
+ read32s(addr + 12),
178
+ ],
179
+ }
180
+ }
181
+ }
182
+ else {
183
+ ptr::read_unaligned(mem8.offset(addr as isize) as *const reg128)
184
+ }
185
+ }
186
+
187
+ #[no_mangle]
188
+ pub unsafe fn write8(addr: u32, value: i32) {
189
+ if in_mapped_range(addr) {
190
+ mmap_write8(addr, value & 0xFF);
191
+ }
192
+ else {
193
+ jit::jit_dirty_page(Page::page_of(addr));
194
+ write8_no_mmap_or_dirty_check(addr, value);
195
+ };
196
+ }
197
+
198
+ pub unsafe fn write8_no_mmap_or_dirty_check(addr: u32, value: i32) {
199
+ *mem8.offset(addr as isize) = value as u8
200
+ }
201
+
202
+ #[no_mangle]
203
+ pub unsafe fn write16(addr: u32, value: i32) {
204
+ if in_mapped_range(addr) {
205
+ mmap_write16(addr, value & 0xFFFF);
206
+ }
207
+ else {
208
+ jit::jit_dirty_cache_small(addr, addr + 2);
209
+ write16_no_mmap_or_dirty_check(addr, value);
210
+ };
211
+ }
212
+ pub unsafe fn write16_no_mmap_or_dirty_check(addr: u32, value: i32) {
213
+ ptr::write_unaligned(mem8.offset(addr as isize) as *mut u16, value as u16)
214
+ }
215
+
216
+ #[no_mangle]
217
+ pub unsafe fn write32(addr: u32, value: i32) {
218
+ if in_mapped_range(addr) {
219
+ mmap_write32(addr, value);
220
+ }
221
+ else {
222
+ jit::jit_dirty_cache_small(addr, addr + 4);
223
+ write32_no_mmap_or_dirty_check(addr, value);
224
+ }
225
+ }
226
+
227
+ pub unsafe fn write32_no_mmap_or_dirty_check(addr: u32, value: i32) {
228
+ ptr::write_unaligned(mem8.offset(addr as isize) as *mut i32, value)
229
+ }
230
+
231
+ pub unsafe fn write64_no_mmap_or_dirty_check(addr: u32, value: u64) {
232
+ ptr::write_unaligned(mem8.offset(addr as isize) as *mut u64, value)
233
+ }
234
+
235
+ pub unsafe fn write128_no_mmap_or_dirty_check(addr: u32, value: reg128) {
236
+ ptr::write_unaligned(mem8.offset(addr as isize) as *mut reg128, value)
237
+ }
238
+
239
+ pub unsafe fn memset_no_mmap_or_dirty_check(addr: u32, value: u8, count: u32) {
240
+ ptr::write_bytes(mem8.offset(addr as isize), value, count as usize);
241
+ }
242
+
243
+ pub unsafe fn memcpy_no_mmap_or_dirty_check(src_addr: u32, dst_addr: u32, count: u32) {
244
+ dbg_assert!(src_addr < *memory_size);
245
+ dbg_assert!(dst_addr < *memory_size);
246
+ ptr::copy(
247
+ mem8.offset(src_addr as isize),
248
+ mem8.offset(dst_addr as isize),
249
+ count as usize,
250
+ )
251
+ }
252
+
253
+ pub unsafe fn memcpy_into_svga_lfb(src_addr: u32, dst_addr: u32, count: u32) {
254
+ dbg_assert!(src_addr < *memory_size);
255
+ dbg_assert!(in_svga_lfb(dst_addr));
256
+ dbg_assert!(Page::page_of(dst_addr) == Page::page_of(dst_addr + count - 1));
257
+ vga::mark_dirty(dst_addr);
258
+ ptr::copy_nonoverlapping(
259
+ mem8.offset(src_addr as isize),
260
+ vga_mem8.offset((dst_addr - VGA_LFB_ADDRESS) as isize),
261
+ count as usize,
262
+ )
263
+ }
264
+
265
+ pub unsafe fn mmap_write8(addr: u32, value: i32) {
266
+ if in_svga_lfb(addr) {
267
+ vga::mark_dirty(addr);
268
+ *vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) = value as u8
269
+ }
270
+ else {
271
+ ext::mmap_write8(addr, value)
272
+ }
273
+ }
274
+ pub unsafe fn mmap_write16(addr: u32, value: i32) {
275
+ if in_svga_lfb(addr) {
276
+ vga::mark_dirty(addr);
277
+ ptr::write_unaligned(
278
+ vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *mut u16,
279
+ value as u16,
280
+ )
281
+ }
282
+ else {
283
+ ext::mmap_write16(addr, value)
284
+ }
285
+ }
286
+ pub unsafe fn mmap_write32(addr: u32, value: i32) {
287
+ if in_svga_lfb(addr) {
288
+ vga::mark_dirty(addr);
289
+ ptr::write_unaligned(
290
+ vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *mut i32,
291
+ value,
292
+ )
293
+ }
294
+ else if addr >= APIC_MEM_ADDRESS && addr < APIC_MEM_ADDRESS + APIC_MEM_SIZE {
295
+ apic::write32(addr - APIC_MEM_ADDRESS, value as u32);
296
+ handle_irqs();
297
+ }
298
+ else if addr >= IOAPIC_MEM_ADDRESS && addr < IOAPIC_MEM_ADDRESS + IOAPIC_MEM_SIZE {
299
+ ioapic::write32(addr - IOAPIC_MEM_ADDRESS, value as u32);
300
+ handle_irqs();
301
+ }
302
+ else {
303
+ ext::mmap_write32(addr, value)
304
+ }
305
+ }
306
+ pub unsafe fn mmap_write64(addr: u32, value: u64) {
307
+ if in_svga_lfb(addr) {
308
+ vga::mark_dirty(addr);
309
+ ptr::write_unaligned(
310
+ vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *mut u64,
311
+ value,
312
+ )
313
+ }
314
+ else {
315
+ ext::mmap_write64(addr, value as i32, (value >> 32) as i32)
316
+ }
317
+ }
318
+ pub unsafe fn mmap_write128(addr: u32, v0: u64, v1: u64) {
319
+ if in_svga_lfb(addr) {
320
+ vga::mark_dirty(addr);
321
+ ptr::write_unaligned(
322
+ vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *mut u64,
323
+ v0,
324
+ );
325
+ ptr::write_unaligned(
326
+ vga_mem8.offset((addr - VGA_LFB_ADDRESS + 8) as isize) as *mut u64,
327
+ v1,
328
+ )
329
+ }
330
+ else {
331
+ ext::mmap_write128(
332
+ addr,
333
+ v0 as i32,
334
+ (v0 >> 32) as i32,
335
+ v1 as i32,
336
+ (v1 >> 32) as i32,
337
+ )
338
+ }
339
+ }
340
+
341
+ #[no_mangle]
342
+ pub unsafe fn is_memory_zeroed(addr: u32, length: u32) -> bool {
343
+ dbg_assert!(addr % 8 == 0);
344
+ dbg_assert!(length % 8 == 0);
345
+ for i in (addr..addr + length).step_by(8) {
346
+ if *(mem8.offset(i as isize) as *const i64) != 0 {
347
+ return false;
348
+ }
349
+ }
350
+ return true;
351
+ }