Skip to content

Commit

Permalink
port pic to rust (XXX: missing state)
Browse files Browse the repository at this point in the history
  • Loading branch information
copy committed Dec 14, 2023
1 parent fe7a0fb commit 03d6595
Show file tree
Hide file tree
Showing 13 changed files with 536 additions and 188 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ CARGO_FLAGS_SAFE=\
CARGO_FLAGS=$(CARGO_FLAGS_SAFE) -C target-feature=+bulk-memory -C target-feature=+multivalue -C target-feature=+simd128

CORE_FILES=const.js config.js io.js main.js lib.js buffer.js ide.js pci.js floppy.js \
memory.js dma.js pit.js vga.js ps2.js pic.js rtc.js uart.js hpet.js \
memory.js dma.js pit.js vga.js ps2.js rtc.js uart.js hpet.js \
acpi.js apic.js ioapic.js \
state.js ne2k.js sb16.js virtio.js bus.js log.js \
cpu.js debug.js \
Expand Down
2 changes: 1 addition & 1 deletion debug.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
var CORE_FILES =
"const.js config.js log.js lib.js buffer.js cpu.js debug.js " +
"io.js main.js ide.js pci.js floppy.js " +
"memory.js dma.js pit.js vga.js ps2.js pic.js rtc.js uart.js acpi.js apic.js ioapic.js hpet.js sb16.js " +
"memory.js dma.js pit.js vga.js ps2.js rtc.js uart.js acpi.js apic.js ioapic.js hpet.js sb16.js " +
"ne2k.js state.js virtio.js bus.js elf.js kernel.js";

var BROWSER_FILES = "main.js screen.js keyboard.js mouse.js speaker.js serial.js network.js starter.js worker_bus.js print_stats.js filestorage.js";
Expand Down
10 changes: 6 additions & 4 deletions src/browser/print_stats.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ const print_stats = {
"SAFE_READ_WRITE_SLOW_HAS_CODE",
"PAGE_FAULT",
"TLB_MISS",
"MAIN_LOOP",
"MAIN_LOOP_IDLE",
"DO_MANY_CYCLES",
"CYCLE_INTERNAL",
"INVALIDATE_ALL_MODULES_NO_FREE_WASM_INDICES",
Expand Down Expand Up @@ -148,13 +150,13 @@ const print_stats = {
text += "JIT_CACHE_SIZE=" + cpu.wm.exports["jit_get_cache_size"]() + "\n";
text += "FLAT_SEGMENTS=" + cpu.wm.exports["has_flat_segmentation"]() + "\n";

text += "do_many_cycles avg: " + (cpu.do_many_cycles_total / cpu.do_many_cycles_count || 0) + "\n";
text += "wasm memory size: " + (cpu.wasm_memory.buffer.byteLength >> 20) + "m\n";

text += "Config:\n";
text += "MAX_PAGES=" + cpu.wm.exports["get_jit_config"](0) + "\n";
text += "JIT_USE_LOOP_SAFETY=" + Boolean(cpu.wm.exports["get_jit_config"](1)) + "\n";
text += "MAX_EXTRA_BASIC_BLOCKS=" + cpu.wm.exports["get_jit_config"](2) + "\n";
text += "JIT_DISABLED=" + cpu.wm.exports["get_jit_config"](0) + "\n";
text += "MAX_PAGES=" + cpu.wm.exports["get_jit_config"](1) + "\n";
text += "JIT_USE_LOOP_SAFETY=" + Boolean(cpu.wm.exports["get_jit_config"](2)) + "\n";
text += "MAX_EXTRA_BASIC_BLOCKS=" + cpu.wm.exports["get_jit_config"](3) + "\n";

return text;
},
Expand Down
11 changes: 6 additions & 5 deletions src/browser/starter.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,12 @@ function V86(options)

const wasm_shared_funcs = {
"cpu_exception_hook": n => this.cpu_exception_hook(n),
"hlt_op": function() { return cpu.hlt_op(); },
"run_hardware_timers": function(t) { return cpu.run_hardware_timers(t); },
"cpu_event_halt": () => { this.emulator_bus.send("cpu-event-halt"); },
"abort": function() { dbg_assert(false); },
"microtick": v86.microtick,
"get_rand_int": function() { return v86util.get_rand_int(); },

"pic_acknowledge": function() { cpu.pic_acknowledge(); },
"apic_acknowledge_irq": function() { cpu.devices.apic.acknowledge_irq(); },

"io_port_read8": function(addr) { return cpu.io.port_read8(addr); },
"io_port_read16": function(addr) { return cpu.io.port_read16(addr); },
Expand Down Expand Up @@ -651,8 +651,9 @@ V86.prototype.zstd_decompress_worker = async function(decompressed_size, src)
if(!wasm)
{
const env = Object.fromEntries([
"cpu_exception_hook", "hlt_op",
"microtick", "get_rand_int", "pic_acknowledge",
"cpu_exception_hook", "run_hardware_timers",
"cpu_event_halt", "microtick", "get_rand_int",
"apic_acknowledge_irq",
"io_port_read8", "io_port_read16", "io_port_read32",
"io_port_write8", "io_port_write16", "io_port_write32",
"mmap_read8", "mmap_read16", "mmap_read32",
Expand Down
7 changes: 0 additions & 7 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,6 @@ var DEBUG_SCREEN_LAYERS = DEBUG && false;
/** @const */
var ENABLE_HPET = DEBUG && false;

/**
* @const
* How often, in milliseconds, to yield to the browser for rendering and
* running events
*/
var TIME_PER_FRAME = 1;

/**
* @const
* How many ticks the TSC does per millisecond
Expand Down
175 changes: 44 additions & 131 deletions src/cpu.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,6 @@ function CPU(bus, wm, next_tick_immediately)

if(DEBUG)
{
this.do_many_cycles_count = 0;
this.do_many_cycles_total = 0;

this.seen_code = {};
this.seen_code_uncompiled = {};
}
Expand Down Expand Up @@ -213,11 +210,9 @@ CPU.prototype.create_jit_imports = function()

CPU.prototype.wasm_patch = function()
{
const get_optional_import = (name) => {
return this.wm.exports[name];
};
const get_optional_import = name => this.wm.exports[name];

const get_import = (name) =>
const get_import = name =>
{
const f = get_optional_import(name);
console.assert(f, "Missing import: " + name);
Expand All @@ -228,12 +223,13 @@ CPU.prototype.wasm_patch = function()

this.getiopl = get_import("getiopl");
this.get_eflags = get_import("get_eflags");
this.get_eflags_no_arith = get_import("get_eflags_no_arith");

this.handle_irqs = get_import("handle_irqs");
this.pic_call_irq = get_import("pic_call_irq");

this.do_many_cycles_native = get_import("do_many_cycles_native");
this.do_many_cycles_native_nojit = get_import("do_many_cycles_native_nojit");
this.main_loop = get_import("main_loop");

this.set_jit_config = get_import("set_jit_config");

this.read8 = get_import("read8");
this.read16 = get_import("read16");
Expand Down Expand Up @@ -262,6 +258,9 @@ CPU.prototype.wasm_patch = function()

this.set_cpuid_level = get_import("set_cpuid_level");

this.pic_set_irq = get_import("pic_set_irq");
this.pic_clear_irq = get_import("pic_clear_irq");

if(DEBUG)
{
this.jit_force_generate_unsafe = get_optional_import("jit_force_generate_unsafe");
Expand All @@ -284,6 +283,21 @@ CPU.prototype.wasm_patch = function()
this.zstd_free_ctx = get_import("zstd_free_ctx");
this.zstd_read = get_import("zstd_read");
this.zstd_read_free = get_import("zstd_read_free");

this.port20_read = get_import("port20_read");
this.port21_read = get_import("port21_read");
this.portA0_read = get_import("portA0_read");
this.portA1_read = get_import("portA1_read");

this.port20_write = get_import("port20_write");
this.port21_write = get_import("port21_write");
this.portA0_write = get_import("portA0_write");
this.portA1_write = get_import("portA1_write");

this.port4D0_read = get_import("port4D0_read");
this.port4D1_read = get_import("port4D1_read");
this.port4D0_write = get_import("port4D0_write");
this.port4D1_write = get_import("port4D1_write");
};

CPU.prototype.jit_force_generate = function(addr)
Expand Down Expand Up @@ -372,7 +386,7 @@ CPU.prototype.get_state = function()
state[57] = this.devices.hda;
state[58] = this.devices.pit;
state[59] = this.devices.net;
state[60] = this.devices.pic;
//state[60] = this.devices.pic;
state[61] = this.devices.sb16;

state[62] = this.fw_value;
Expand Down Expand Up @@ -468,7 +482,7 @@ CPU.prototype.set_state = function(state)
this.devices.hda && this.devices.hda.set_state(state[57]);
this.devices.pit && this.devices.pit.set_state(state[58]);
this.devices.net && this.devices.net.set_state(state[59]);
this.devices.pic && this.devices.pic.set_state(state[60]);
//this.devices.pic && this.devices.pic.set_state(state[60]);
this.devices.sb16 && this.devices.sb16.set_state(state[61]);

this.devices.uart1 && this.devices.uart1.set_state(state[79]);
Expand Down Expand Up @@ -566,42 +580,6 @@ CPU.prototype.unpack_memory = function(bitmap, packed_memory)
}
};

/**
* @return {number} time in ms until this method should becalled again
*/
CPU.prototype.main_run = function()
{
if(this.in_hlt[0])
{
const t = this.hlt_loop();

if(this.in_hlt[0])
{
return t;
}
}

const start = v86.microtick();
let now = start;

for(; now - start < TIME_PER_FRAME;)
{
this.do_many_cycles();

now = v86.microtick();

const t = this.run_hardware_timers(now);
this.handle_irqs();

if(this.in_hlt[0])
{
return t;
}
}

return 0;
};

CPU.prototype.reboot_internal = function()
{
this.reset_cpu();
Expand Down Expand Up @@ -660,7 +638,7 @@ CPU.prototype.init = function(settings, device_bus)

if(settings.disable_jit)
{
this.do_many_cycles_native = this.do_many_cycles_native_nojit;
this.set_jit_config(0, 1);
}

settings.cpuid_level && this.set_cpuid_level(settings.cpuid_level);
Expand Down Expand Up @@ -819,12 +797,26 @@ CPU.prototype.init = function(settings, device_bus)
io.register_write(0xE9, this, function(out_byte) {});
}

io.register_read(0x20, this, this.port20_read);
io.register_read(0x21, this, this.port21_read);
io.register_read(0xA0, this, this.portA0_read);
io.register_read(0xA1, this, this.portA1_read);

io.register_write(0x20, this, this.port20_write);
io.register_write(0x21, this, this.port21_write);
io.register_write(0xA0, this, this.portA0_write);
io.register_write(0xA1, this, this.portA1_write);

io.register_read(0x4D0, this, this.port4D0_read);
io.register_read(0x4D1, this, this.port4D1_read);
io.register_write(0x4D0, this, this.port4D0_write);
io.register_write(0x4D1, this, this.port4D1_write);

this.devices = {};

// TODO: Make this more configurable
if(settings.load_devices)
{
this.devices.pic = new PIC(this);
this.devices.pci = new PCI(this);

if(this.acpi_enabled[0])
Expand Down Expand Up @@ -1224,22 +1216,6 @@ CPU.prototype.load_bios = function()
}.bind(this));
};

CPU.prototype.do_many_cycles = function()
{
if(DEBUG)
{
var start_time = v86.microtick();
}

this.do_many_cycles_native();

if(DEBUG)
{
this.do_many_cycles_total += v86.microtick() - start_time;
this.do_many_cycles_count++;
}
};

CPU.prototype.codegen_finalize = function(wasm_table_index, start, state_flags, ptr, len)
{
ptr >>>= 0;
Expand Down Expand Up @@ -1398,20 +1374,6 @@ CPU.prototype.dump_function_code = function(block_ptr, count)
}
};

CPU.prototype.hlt_loop = function()
{
if(this.get_eflags_no_arith() & FLAG_INTERRUPT)
{
const t = this.run_hardware_timers(v86.microtick());
this.handle_irqs();
return t;
}
else
{
return 100;
}
};

CPU.prototype.run_hardware_timers = function(now)
{
if(ENABLE_HPET)
Expand All @@ -1438,56 +1400,10 @@ CPU.prototype.run_hardware_timers = function(now)
return Math.min(pit_time, rtc_time, hpet_time, acpi_time, apic_time);
};

CPU.prototype.hlt_op = function()
{
if((this.get_eflags_no_arith() & FLAG_INTERRUPT) === 0)
{
// execution can never resume (until NMIs are supported)
this.bus.send("cpu-event-halt");
}

// get out of here and into hlt_loop
this.in_hlt[0] = +true;

// Try an hlt loop right now: This will run timer interrupts, and if one is
// due it will immediately call call_interrupt_vector and continue
// execution without an unnecessary cycle through do_run
this.hlt_loop();
};

CPU.prototype.handle_irqs = function()
{
//dbg_assert(this.prefixes[0] === 0);

if(this.get_eflags_no_arith() & FLAG_INTERRUPT)
{
this.pic_acknowledge();
this.next_tick_immediately();
}
};

CPU.prototype.pic_acknowledge = function()
{
dbg_assert(this.get_eflags_no_arith() & FLAG_INTERRUPT);

if(this.devices.pic)
{
this.devices.pic.acknowledge_irq();
}

if(this.devices.apic)
{
this.devices.apic.acknowledge_irq();
}
};

CPU.prototype.device_raise_irq = function(i)
{
dbg_assert(arguments.length === 1);
if(this.devices.pic)
{
this.devices.pic.set_irq(i);
}
this.pic_set_irq(i);

if(this.devices.ioapic)
{
Expand All @@ -1497,10 +1413,7 @@ CPU.prototype.device_raise_irq = function(i)

CPU.prototype.device_lower_irq = function(i)
{
if(this.devices.pic)
{
this.devices.pic.clear_irq(i);
}
this.pic_clear_irq(i);

if(this.devices.ioapic)
{
Expand Down
2 changes: 1 addition & 1 deletion src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ v86.prototype.do_tick = function()
}

this.idle = false;
const t = this.cpu.main_run();
const t = this.cpu.main_loop();

this.next_tick(t);
};
Expand Down

0 comments on commit 03d6595

Please sign in to comment.