From 3ef26120ee8734c0f61054e9d35c67a36b9748dd Mon Sep 17 00:00:00 2001 From: StrikerX3 Date: Wed, 20 Feb 2019 23:38:36 -0300 Subject: [PATCH] Replace CPU modules with virt86 Restructure CMake projects --- .gitignore | 46 +- CMakeLists.txt | 79 +- README.md | 51 +- apps/CMakeLists.txt | 2 + apps/cli/CMakeLists.txt | 54 ++ {src/cli => apps/cli/src}/lib/cxxopts.hpp | 0 {src/cli => apps/cli/src}/main.cpp | 47 +- apps/cli/src/pch.cpp | 26 + apps/cli/src/pch.hpp | 29 + cmake/PrecompiledHeader.cmake | 206 +++-- cmake/VSHelpers.cmake | 28 +- modules/CMakeLists.txt | 2 + modules/core/CMakeLists.txt | 173 ++++ modules/core/cmake/Config.cmake.in | 27 + .../core/include}/vixen/alloc.h | 0 .../core/include}/vixen/core.h | 1 - .../core/include}/vixen/cxbxtimer.h | 0 modules/core/include/vixen/debug.h | 29 + .../core/include}/vixen/dynamic_variant.h | 0 .../core/include}/vixen/gdbserver.h | 11 +- .../core/include}/vixen/hw/ata/ata.h | 4 +- .../core/include}/vixen/hw/ata/ata_channel.h | 1 - .../core/include}/vixen/hw/ata/ata_common.h | 0 .../core/include}/vixen/hw/ata/ata_defs.h | 0 .../core/include}/vixen/hw/ata/ata_device.h | 0 .../include}/vixen/hw/ata/cmds/ata_command.h | 0 .../vixen/hw/ata/cmds/cmd_identify_device.h | 0 .../hw/ata/cmds/cmd_identify_packet_device.h | 0 .../vixen/hw/ata/cmds/cmd_init_dev_params.h | 0 .../include}/vixen/hw/ata/cmds/cmd_packet.h | 0 .../include}/vixen/hw/ata/cmds/cmd_read_dma.h | 0 .../vixen/hw/ata/cmds/cmd_security_unlock.h | 0 .../vixen/hw/ata/cmds/cmd_set_features.h | 0 .../vixen/hw/ata/cmds/cmd_write_dma.h | 0 .../include}/vixen/hw/ata/cmds/proto_dma.h | 0 .../vixen/hw/ata/cmds/proto_nondata.h | 0 .../include}/vixen/hw/ata/cmds/proto_packet.h | 0 .../vixen/hw/ata/cmds/proto_pio_data_in.h | 0 .../vixen/hw/ata/cmds/proto_pio_data_out.h | 0 .../vixen/hw/ata/drvs/ata_device_driver.h | 0 .../include}/vixen/hw/ata/drvs/drv_null.h | 0 .../vixen/hw/ata/drvs/drv_vdvd_base.h | 0 .../vixen/hw/ata/drvs/drv_vdvd_dummy.h | 0 .../vixen/hw/ata/drvs/drv_vdvd_image.h | 0 .../include}/vixen/hw/ata/drvs/drv_vhd_base.h | 0 .../vixen/hw/ata/drvs/drv_vhd_dummy.h | 0 .../vixen/hw/ata/drvs/drv_vhd_image.h | 0 .../core/include}/vixen/hw/ata/drvs/util.h | 0 .../include}/vixen/hw/atapi/atapi_common.h | 0 .../core/include}/vixen/hw/atapi/atapi_defs.h | 0 .../include}/vixen/hw/atapi/atapi_utils.h | 0 .../core/include}/vixen/hw/atapi/atapi_xbox.h | 0 .../vixen/hw/atapi/cmds/atapi_command.h | 0 .../vixen/hw/atapi/cmds/cmd_mode_sense_10.h | 0 .../vixen/hw/atapi/cmds/cmd_read_10.h | 0 .../vixen/hw/atapi/cmds/cmd_read_capacity.h | 0 .../hw/atapi/cmds/cmd_read_dvd_structure.h | 0 .../vixen/hw/atapi/cmds/cmd_test_unit_ready.h | 0 .../vixen/hw/atapi/cmds/proto_data_in.h | 0 .../vixen/hw/atapi/cmds/proto_nondata.h | 0 .../core/include}/vixen/hw/basic/char.h | 1 - .../core/include}/vixen/hw/basic/char_null.h | 0 .../core/include}/vixen/hw/basic/cmos.h | 4 +- .../core/include}/vixen/hw/basic/gsi.h | 0 .../core/include}/vixen/hw/basic/i8254.h | 0 .../core/include}/vixen/hw/basic/i8259.h | 15 +- .../core/include}/vixen/hw/basic/interrupt.h | 0 .../core/include}/vixen/hw/basic/ioapic.h | 0 .../core/include}/vixen/hw/basic/irq.h | 0 .../core/include}/vixen/hw/basic/mcpx.h | 0 .../core/include}/vixen/hw/basic/serial.h | 2 +- .../core/include}/vixen/hw/basic/superio.h | 1 - .../core/include}/vixen/hw/bus/isabus.h | 0 .../core/include}/vixen/hw/bus/pcibus.h | 0 .../core/include}/vixen/hw/bus/smbus.h | 0 .../core/include}/vixen/hw/defs.h | 0 .../core/include}/vixen/hw/nv2a/defs.h | 0 .../core/include}/vixen/hw/nv2a/nv2a_int.h | 0 .../core/include}/vixen/hw/nv2a/vga.h | 0 .../core/include}/vixen/hw/ohci/ohci.h | 9 +- .../core/include}/vixen/hw/ohci/ohci_common.h | 0 .../core/include}/vixen/hw/ohci/ohci_hub.h | 0 .../core/include}/vixen/hw/pci/ac97.h | 0 .../core/include}/vixen/hw/pci/agpbridge.h | 0 .../core/include}/vixen/hw/pci/bmide.h | 2 +- .../include}/vixen/hw/pci/bmide_channel.h | 2 +- .../core/include/vixen/hw/pci}/bmide_defs.h | 0 .../core/include}/vixen/hw/pci/hostbridge.h | 0 .../core/include}/vixen/hw/pci/lpc.h | 0 .../core/include}/vixen/hw/pci/mcpx_ram.h | 0 .../core/include}/vixen/hw/pci/nv2a.h | 0 .../core/include}/vixen/hw/pci/nvapu.h | 0 .../core/include}/vixen/hw/pci/nvnet.h | 0 .../core/include}/vixen/hw/pci/pci.h | 0 .../core/include}/vixen/hw/pci/pci_common.h | 0 .../core/include}/vixen/hw/pci/pci_irq.h | 0 .../core/include}/vixen/hw/pci/pci_regs.h | 0 .../core/include}/vixen/hw/pci/pcibridge.h | 0 .../core/include}/vixen/hw/pci/usb_pci.h | 9 +- .../core/include}/vixen/hw/sm/adm1032.h | 0 .../core/include}/vixen/hw/sm/eeprom.h | 0 .../core/include}/vixen/hw/sm/led.h | 0 .../core/include}/vixen/hw/sm/sm.h | 0 .../core/include}/vixen/hw/sm/smc.h | 0 .../core/include}/vixen/hw/sm/tvenc.h | 0 .../include}/vixen/hw/sm/tvenc_conexant.h | 0 .../core/include}/vixen/hw/utils.h | 0 .../core/include}/vixen/hw/xid/xid_gamepad.h | 0 .../core/include}/vixen/io.h | 0 .../core/include}/vixen/iovec.h | 0 .../core/include}/vixen/log.h | 0 .../core => modules/core/include}/vixen/mem.h | 6 +- .../core/include}/vixen/queue.h | 0 .../core/include}/vixen/settings.h | 0 modules/core/include/vixen/status.h | 30 + .../core/include}/vixen/thread.h | 0 .../core/include}/vixen/timer.h | 0 .../core/include}/vixen/util.h | 3 - .../core/include}/vixen/util/fifo.h | 0 .../core/include}/vixen/util/invoke_later.h | 0 .../core/include}/vixen/xbox.h | 32 +- .../vixen => modules/core/src/common}/pch.cpp | 2 +- .../pch.h => modules/core/src/common/pch.hpp | 4 +- .../core/src/common}/vixen/core.cpp | 0 .../core/src}/common/vixen/cxbxtimer.cpp | 2 +- modules/core/src/common/vixen/debug.cpp | 292 ++++++ .../core/src/common}/vixen/gdbserver.cpp | 70 +- .../core/src/common}/vixen/hw/ata/ata.cpp | 2 +- .../src/common}/vixen/hw/ata/ata_channel.cpp | 2 +- .../src/common}/vixen/hw/ata/ata_common.cpp | 2 +- .../src/common}/vixen/hw/ata/ata_device.cpp | 2 +- .../common}/vixen/hw/ata/cmds/ata_command.cpp | 2 +- .../vixen/hw/ata/cmds/cmd_identify_device.cpp | 2 +- .../ata/cmds/cmd_identify_packet_device.cpp | 2 +- .../vixen/hw/ata/cmds/cmd_init_dev_params.cpp | 2 +- .../common}/vixen/hw/ata/cmds/cmd_packet.cpp | 2 +- .../vixen/hw/ata/cmds/cmd_read_dma.cpp | 2 +- .../vixen/hw/ata/cmds/cmd_security_unlock.cpp | 2 +- .../vixen/hw/ata/cmds/cmd_set_features.cpp | 2 +- .../vixen/hw/ata/cmds/cmd_write_dma.cpp | 2 +- .../common}/vixen/hw/ata/cmds/proto_dma.cpp | 2 +- .../vixen/hw/ata/cmds/proto_nondata.cpp | 2 +- .../vixen/hw/ata/cmds/proto_packet.cpp | 736 +++++++-------- .../vixen/hw/ata/cmds/proto_pio_data_in.cpp | 2 +- .../vixen/hw/ata/cmds/proto_pio_data_out.cpp | 2 +- .../vixen/hw/ata/drvs/ata_device_driver.cpp | 2 +- .../common}/vixen/hw/ata/drvs/drv_null.cpp | 2 +- .../vixen/hw/ata/drvs/drv_vdvd_base.cpp | 2 +- .../vixen/hw/ata/drvs/drv_vdvd_dummy.cpp | 2 +- .../vixen/hw/ata/drvs/drv_vdvd_image.cpp | 2 +- .../vixen/hw/ata/drvs/drv_vhd_base.cpp | 2 +- .../vixen/hw/ata/drvs/drv_vhd_dummy.cpp | 2 +- .../vixen/hw/ata/drvs/drv_vhd_image.cpp | 2 +- .../src/common}/vixen/hw/ata/drvs/util.cpp | 2 +- .../common}/vixen/hw/atapi/atapi_common.cpp | 2 +- .../vixen/hw/atapi/cmds/atapi_command.cpp | 2 +- .../vixen/hw/atapi/cmds/cmd_mode_sense_10.cpp | 2 +- .../vixen/hw/atapi/cmds/cmd_read_10.cpp | 2 +- .../vixen/hw/atapi/cmds/cmd_read_capacity.cpp | 2 +- .../hw/atapi/cmds/cmd_read_dvd_structure.cpp | 2 +- .../hw/atapi/cmds/cmd_test_unit_ready.cpp | 2 +- .../vixen/hw/atapi/cmds/proto_data_in.cpp | 2 +- .../vixen/hw/atapi/cmds/proto_nondata.cpp | 2 +- .../core/src/common/vixen/hw/basic/char.cpp | 7 + .../src/common}/vixen/hw/basic/char_null.cpp | 2 +- .../core/src/common}/vixen/hw/basic/cmos.cpp | 2 +- .../core/src/common}/vixen/hw/basic/gsi.cpp | 2 +- .../core/src/common}/vixen/hw/basic/i8254.cpp | 4 +- .../core/src/common}/vixen/hw/basic/i8259.cpp | 10 +- .../core/src/common}/vixen/hw/basic/irq.cpp | 2 +- .../core/src/common}/vixen/hw/basic/mcpx.cpp | 5 +- .../src/common}/vixen/hw/basic/serial.cpp | 2 +- .../src/common}/vixen/hw/basic/superio.cpp | 2 +- .../core/src/common}/vixen/hw/bus/isabus.cpp | 3 +- .../core/src/common}/vixen/hw/bus/pcibus.cpp | 3 +- .../core/src/common}/vixen/hw/bus/smbus.cpp | 3 +- .../core/src/common}/vixen/hw/ohci/ohci.cpp | 25 +- .../src/common}/vixen/hw/ohci/ohci_hub.cpp | 6 +- .../core/src/common}/vixen/hw/pci/ac97.cpp | 3 +- .../src/common}/vixen/hw/pci/agpbridge.cpp | 3 +- .../core/src/common}/vixen/hw/pci/bmide.cpp | 3 +- .../common}/vixen/hw/pci/bmide_channel.cpp | 3 +- .../src/common}/vixen/hw/pci/hostbridge.cpp | 3 +- .../core/src/common}/vixen/hw/pci/lpc.cpp | 5 +- .../src/common}/vixen/hw/pci/mcpx_ram.cpp | 3 +- .../core/src/common}/vixen/hw/pci/nv2a.cpp | 3 +- .../core/src/common}/vixen/hw/pci/nvapu.cpp | 3 +- .../core/src/common}/vixen/hw/pci/nvnet.cpp | 3 +- .../core/src/common}/vixen/hw/pci/pci.cpp | 5 +- .../core/src/common}/vixen/hw/pci/pci_irq.cpp | 2 +- .../src/common}/vixen/hw/pci/pcibridge.cpp | 5 +- .../core/src/common}/vixen/hw/pci/usb_pci.cpp | 12 +- .../core/src/common}/vixen/hw/sm/adm1032.cpp | 2 +- .../core/src/common}/vixen/hw/sm/eeprom.cpp | 2 +- modules/core/src/common/vixen/hw/sm/sm.cpp | 7 + .../core/src/common}/vixen/hw/sm/smc.cpp | 5 +- .../core/src/common}/vixen/hw/sm/tvenc.cpp | 2 +- .../common}/vixen/hw/sm/tvenc_conexant.cpp | 2 +- .../src/common}/vixen/hw/xid/xid_gamepad.cpp | 7 +- {src => modules/core/src}/common/vixen/io.cpp | 2 +- .../core/src}/common/vixen/iovec.cpp | 2 +- .../core/src}/common/vixen/log.cpp | 3 +- .../core/src/common}/vixen/timer.cpp | 3 +- modules/core/src/common/vixen/util/fifo.cpp | 7 + .../src/common}/vixen/util/invoke_later.cpp | 2 +- .../core/src/common}/vixen/xbox.cpp | 296 +++--- .../core/src}/linux/thread.cpp | 0 .../core/src/windows}/thread.cpp | 0 .../vixen/hw/basic/win32/char_serial.cpp | 0 .../vixen/hw/basic/win32/char_serial.h | 2 +- .../vixen/hw/basic/win32/mt_serial.cpp | 0 .../windows}/vixen/hw/basic/win32/mt_serial.h | 0 src/cli/CMakeLists.txt | 88 -- src/cli/lib/CMakeLists.txt | 13 - src/common/CMakeLists.txt | 39 - src/common/vixen/bitmap.h | 32 - src/common/vixen/gdt.cpp | 19 - src/common/vixen/gdt.h | 38 - src/common/vixen/idt.cpp | 28 - src/common/vixen/idt.h | 32 - src/common/vixen/linux/CMakeLists.txt | 13 - src/common/vixen/linux/shlibrary.cpp | 57 -- src/common/vixen/memregion.h | 80 -- src/common/vixen/platform.h | 19 - src/common/vixen/pte.h | 31 - src/common/vixen/shlibrary.cpp | 9 - src/common/vixen/shlibrary.h | 48 - src/common/vixen/status.h | 74 -- src/common/vixen/win32/CMakeLists.txt | 13 - src/common/vixen/win32/shlibrary.cpp | 52 -- src/core/CMakeLists.txt | 60 -- src/core/vixen/.gitignore | 5 - src/core/vixen/debug.cpp | 188 ---- src/core/vixen/debug.h | 30 - src/core/vixen/dev.cpp | 14 - src/core/vixen/dev.h | 16 - src/core/vixen/emulator.h | 14 - src/core/vixen/hw/CMakeLists.txt | 43 - src/core/vixen/hw/basic/char.cpp | 7 - src/core/vixen/hw/basic/win32/CMakeLists.txt | 13 - src/core/vixen/hw/sm/sm.cpp | 7 - src/core/vixen/memregion.cpp | 64 -- src/core/vixen/module.cpp | 138 --- src/core/vixen/module.h | 78 -- src/core/vixen/util/CMakeLists.txt | 13 - src/core/vixen/util/fifo.cpp | 7 - src/core/vixen/xbe.cpp | 873 ------------------ src/core/vixen/xbe.h | 382 -------- src/cpu-module-haxm/CMakeLists.txt | 48 - src/cpu-module-haxm/cpu_haxm.cpp | 500 ---------- src/cpu-module-haxm/cpu_haxm.h | 78 -- src/cpu-module-haxm/cpu_haxm_module.cpp | 28 - src/cpu-module-haxm/cpu_haxm_module.h | 23 - .../haxm/darwin/hax_interface_mac.h | 74 -- .../haxm/darwin/hax_types_mac.h | 39 - src/cpu-module-haxm/haxm/hax_interface.h | 291 ------ src/cpu-module-haxm/haxm/hax_types.h | 179 ---- src/cpu-module-haxm/haxm/haxm.cpp | 687 -------------- src/cpu-module-haxm/haxm/haxm.h | 185 ---- .../haxm/linux/hax_interface_linux.h | 75 -- .../haxm/linux/hax_types_linux.h | 60 -- src/cpu-module-haxm/haxm/vcpu_state.h | 193 ---- .../haxm/windows/hax_interface_windows.h | 96 -- .../haxm/windows/hax_types_windows.h | 64 -- src/cpu-module-kvm/CMakeLists.txt | 38 - src/cpu-module-kvm/cpu_kvm.cpp | 432 --------- src/cpu-module-kvm/cpu_kvm.h | 72 -- src/cpu-module-kvm/cpu_kvm_module.cpp | 28 - src/cpu-module-kvm/cpu_kvm_module.h | 23 - src/cpu-module-kvm/kvm/kvm.cpp | 254 ----- src/cpu-module-kvm/kvm/kvm.h | 107 --- src/cpu-module-whvp/CMakeLists.txt | 48 - src/cpu-module-whvp/cpu_whvp.cpp | 479 ---------- src/cpu-module-whvp/cpu_whvp.h | 54 -- src/cpu-module-whvp/cpu_whvp_module.cpp | 27 - src/cpu-module-whvp/cpu_whvp_module.h | 21 - src/cpu-module-whvp/whvp/whvp.cpp | 468 ---------- src/cpu-module-whvp/whvp/whvp.h | 149 --- src/cpu-module/CMakeLists.txt | 31 - src/cpu-module/vixen/cpu.cpp | 462 --------- src/cpu-module/vixen/cpu.h | 541 ----------- src/cpu-module/vixen/cpu_module.h | 59 -- src/cpu-module/vixen/cpu_module_decl.h | 68 -- src/module-common/CMakeLists.txt | 30 - src/module-common/vixen/module_common.cpp | 3 - src/module-common/vixen/module_common.h | 53 -- 286 files changed, 1679 insertions(+), 9611 deletions(-) create mode 100644 apps/CMakeLists.txt create mode 100644 apps/cli/CMakeLists.txt rename {src/cli => apps/cli/src}/lib/cxxopts.hpp (100%) rename {src/cli => apps/cli/src}/main.cpp (81%) create mode 100644 apps/cli/src/pch.cpp create mode 100644 apps/cli/src/pch.hpp create mode 100644 modules/CMakeLists.txt create mode 100644 modules/core/CMakeLists.txt create mode 100644 modules/core/cmake/Config.cmake.in rename {src/core => modules/core/include}/vixen/alloc.h (100%) rename {src/core => modules/core/include}/vixen/core.h (87%) rename {src/common => modules/core/include}/vixen/cxbxtimer.h (100%) create mode 100644 modules/core/include/vixen/debug.h rename {src/common => modules/core/include}/vixen/dynamic_variant.h (100%) rename {src/core => modules/core/include}/vixen/gdbserver.h (96%) rename {src/core => modules/core/include}/vixen/hw/ata/ata.h (95%) rename {src/core => modules/core/include}/vixen/hw/ata/ata_channel.h (99%) rename {src/core => modules/core/include}/vixen/hw/ata/ata_common.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/ata_defs.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/ata_device.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/cmds/ata_command.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/cmds/cmd_identify_device.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/cmds/cmd_identify_packet_device.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/cmds/cmd_init_dev_params.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/cmds/cmd_packet.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/cmds/cmd_read_dma.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/cmds/cmd_security_unlock.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/cmds/cmd_set_features.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/cmds/cmd_write_dma.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/cmds/proto_dma.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/cmds/proto_nondata.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/cmds/proto_packet.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/cmds/proto_pio_data_in.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/cmds/proto_pio_data_out.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/drvs/ata_device_driver.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/drvs/drv_null.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/drvs/drv_vdvd_base.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/drvs/drv_vdvd_dummy.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/drvs/drv_vdvd_image.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/drvs/drv_vhd_base.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/drvs/drv_vhd_dummy.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/drvs/drv_vhd_image.h (100%) rename {src/core => modules/core/include}/vixen/hw/ata/drvs/util.h (100%) rename {src/core => modules/core/include}/vixen/hw/atapi/atapi_common.h (100%) rename {src/core => modules/core/include}/vixen/hw/atapi/atapi_defs.h (100%) rename {src/core => modules/core/include}/vixen/hw/atapi/atapi_utils.h (100%) rename {src/core => modules/core/include}/vixen/hw/atapi/atapi_xbox.h (100%) rename {src/core => modules/core/include}/vixen/hw/atapi/cmds/atapi_command.h (100%) rename {src/core => modules/core/include}/vixen/hw/atapi/cmds/cmd_mode_sense_10.h (100%) rename {src/core => modules/core/include}/vixen/hw/atapi/cmds/cmd_read_10.h (100%) rename {src/core => modules/core/include}/vixen/hw/atapi/cmds/cmd_read_capacity.h (100%) rename {src/core => modules/core/include}/vixen/hw/atapi/cmds/cmd_read_dvd_structure.h (100%) rename {src/core => modules/core/include}/vixen/hw/atapi/cmds/cmd_test_unit_ready.h (100%) rename {src/core => modules/core/include}/vixen/hw/atapi/cmds/proto_data_in.h (100%) rename {src/core => modules/core/include}/vixen/hw/atapi/cmds/proto_nondata.h (100%) rename {src/core => modules/core/include}/vixen/hw/basic/char.h (98%) rename {src/core => modules/core/include}/vixen/hw/basic/char_null.h (100%) rename {src/core => modules/core/include}/vixen/hw/basic/cmos.h (98%) rename {src/core => modules/core/include}/vixen/hw/basic/gsi.h (100%) rename {src/core => modules/core/include}/vixen/hw/basic/i8254.h (100%) rename {src/core => modules/core/include}/vixen/hw/basic/i8259.h (93%) rename {src/core => modules/core/include}/vixen/hw/basic/interrupt.h (100%) rename {src/core => modules/core/include}/vixen/hw/basic/ioapic.h (100%) rename {src/core => modules/core/include}/vixen/hw/basic/irq.h (100%) rename {src/core => modules/core/include}/vixen/hw/basic/mcpx.h (100%) rename {src/core => modules/core/include}/vixen/hw/basic/serial.h (99%) rename {src/core => modules/core/include}/vixen/hw/basic/superio.h (98%) rename {src/core => modules/core/include}/vixen/hw/bus/isabus.h (100%) rename {src/core => modules/core/include}/vixen/hw/bus/pcibus.h (100%) rename {src/core => modules/core/include}/vixen/hw/bus/smbus.h (100%) rename {src/core => modules/core/include}/vixen/hw/defs.h (100%) rename {src/core => modules/core/include}/vixen/hw/nv2a/defs.h (100%) rename {src/core => modules/core/include}/vixen/hw/nv2a/nv2a_int.h (100%) rename {src/core => modules/core/include}/vixen/hw/nv2a/vga.h (100%) rename {src/core => modules/core/include}/vixen/hw/ohci/ohci.h (98%) rename {src/core => modules/core/include}/vixen/hw/ohci/ohci_common.h (100%) rename {src/core => modules/core/include}/vixen/hw/ohci/ohci_hub.h (100%) rename {src/core => modules/core/include}/vixen/hw/pci/ac97.h (100%) rename {src/core => modules/core/include}/vixen/hw/pci/agpbridge.h (100%) rename {src/core => modules/core/include}/vixen/hw/pci/bmide.h (97%) rename {src/core => modules/core/include}/vixen/hw/pci/bmide_channel.h (98%) rename {src/core/vixen/hw/pci/bmide => modules/core/include/vixen/hw/pci}/bmide_defs.h (100%) rename {src/core => modules/core/include}/vixen/hw/pci/hostbridge.h (100%) rename {src/core => modules/core/include}/vixen/hw/pci/lpc.h (100%) rename {src/core => modules/core/include}/vixen/hw/pci/mcpx_ram.h (100%) rename {src/core => modules/core/include}/vixen/hw/pci/nv2a.h (100%) rename {src/core => modules/core/include}/vixen/hw/pci/nvapu.h (100%) rename {src/core => modules/core/include}/vixen/hw/pci/nvnet.h (100%) rename {src/core => modules/core/include}/vixen/hw/pci/pci.h (100%) rename {src/core => modules/core/include}/vixen/hw/pci/pci_common.h (100%) rename {src/core => modules/core/include}/vixen/hw/pci/pci_irq.h (100%) rename {src/core => modules/core/include}/vixen/hw/pci/pci_regs.h (100%) rename {src/core => modules/core/include}/vixen/hw/pci/pcibridge.h (100%) rename {src/core => modules/core/include}/vixen/hw/pci/usb_pci.h (98%) rename {src/core => modules/core/include}/vixen/hw/sm/adm1032.h (100%) rename {src/core => modules/core/include}/vixen/hw/sm/eeprom.h (100%) rename {src/core => modules/core/include}/vixen/hw/sm/led.h (100%) rename {src/core => modules/core/include}/vixen/hw/sm/sm.h (100%) rename {src/core => modules/core/include}/vixen/hw/sm/smc.h (100%) rename {src/core => modules/core/include}/vixen/hw/sm/tvenc.h (100%) rename {src/core => modules/core/include}/vixen/hw/sm/tvenc_conexant.h (100%) rename {src/core => modules/core/include}/vixen/hw/utils.h (100%) rename {src/core => modules/core/include}/vixen/hw/xid/xid_gamepad.h (100%) rename {src/common => modules/core/include}/vixen/io.h (100%) rename {src/common => modules/core/include}/vixen/iovec.h (100%) rename {src/common => modules/core/include}/vixen/log.h (100%) rename {src/core => modules/core/include}/vixen/mem.h (84%) rename {src/common => modules/core/include}/vixen/queue.h (100%) rename {src/core => modules/core/include}/vixen/settings.h (100%) create mode 100644 modules/core/include/vixen/status.h rename {src/common => modules/core/include}/vixen/thread.h (100%) rename {src/core => modules/core/include}/vixen/timer.h (100%) rename {src/core => modules/core/include}/vixen/util.h (95%) rename {src/core => modules/core/include}/vixen/util/fifo.h (100%) rename {src/core => modules/core/include}/vixen/util/invoke_later.h (100%) rename {src/core => modules/core/include}/vixen/xbox.h (83%) rename {src/core/vixen => modules/core/src/common}/pch.cpp (84%) rename src/core/vixen/pch.h => modules/core/src/common/pch.hpp (85%) rename {src/core => modules/core/src/common}/vixen/core.cpp (100%) rename {src => modules/core/src}/common/vixen/cxbxtimer.cpp (99%) create mode 100644 modules/core/src/common/vixen/debug.cpp rename {src/core => modules/core/src/common}/vixen/gdbserver.cpp (93%) rename {src/core => modules/core/src/common}/vixen/hw/ata/ata.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/ata/ata_channel.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/ata/ata_common.cpp (96%) rename {src/core => modules/core/src/common}/vixen/hw/ata/ata_device.cpp (95%) rename {src/core => modules/core/src/common}/vixen/hw/ata/cmds/ata_command.cpp (95%) rename {src/core => modules/core/src/common}/vixen/hw/ata/cmds/cmd_identify_device.cpp (97%) rename {src/core => modules/core/src/common}/vixen/hw/ata/cmds/cmd_identify_packet_device.cpp (97%) rename {src/core => modules/core/src/common}/vixen/hw/ata/cmds/cmd_init_dev_params.cpp (98%) rename {src/core => modules/core/src/common}/vixen/hw/ata/cmds/cmd_packet.cpp (94%) rename {src/core => modules/core/src/common}/vixen/hw/ata/cmds/cmd_read_dma.cpp (93%) rename {src/core => modules/core/src/common}/vixen/hw/ata/cmds/cmd_security_unlock.cpp (95%) rename {src/core => modules/core/src/common}/vixen/hw/ata/cmds/cmd_set_features.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/ata/cmds/cmd_write_dma.cpp (93%) rename {src/core => modules/core/src/common}/vixen/hw/ata/cmds/proto_dma.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/ata/cmds/proto_nondata.cpp (96%) rename {src/core => modules/core/src/common}/vixen/hw/ata/cmds/proto_packet.cpp (97%) rename {src/core => modules/core/src/common}/vixen/hw/ata/cmds/proto_pio_data_in.cpp (98%) rename {src/core => modules/core/src/common}/vixen/hw/ata/cmds/proto_pio_data_out.cpp (98%) rename {src/core => modules/core/src/common}/vixen/hw/ata/drvs/ata_device_driver.cpp (94%) rename {src/core => modules/core/src/common}/vixen/hw/ata/drvs/drv_null.cpp (95%) rename {src/core => modules/core/src/common}/vixen/hw/ata/drvs/drv_vdvd_base.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/ata/drvs/drv_vdvd_dummy.cpp (95%) rename {src/core => modules/core/src/common}/vixen/hw/ata/drvs/drv_vdvd_image.cpp (98%) rename {src/core => modules/core/src/common}/vixen/hw/ata/drvs/drv_vhd_base.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/ata/drvs/drv_vhd_dummy.cpp (97%) rename {src/core => modules/core/src/common}/vixen/hw/ata/drvs/drv_vhd_image.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/ata/drvs/util.cpp (89%) rename {src/core => modules/core/src/common}/vixen/hw/atapi/atapi_common.cpp (98%) rename {src/core => modules/core/src/common}/vixen/hw/atapi/cmds/atapi_command.cpp (96%) rename {src/core => modules/core/src/common}/vixen/hw/atapi/cmds/cmd_mode_sense_10.cpp (97%) rename {src/core => modules/core/src/common}/vixen/hw/atapi/cmds/cmd_read_10.cpp (98%) rename {src/core => modules/core/src/common}/vixen/hw/atapi/cmds/cmd_read_capacity.cpp (97%) rename {src/core => modules/core/src/common}/vixen/hw/atapi/cmds/cmd_read_dvd_structure.cpp (98%) rename {src/core => modules/core/src/common}/vixen/hw/atapi/cmds/cmd_test_unit_ready.cpp (97%) rename {src/core => modules/core/src/common}/vixen/hw/atapi/cmds/proto_data_in.cpp (97%) rename {src/core => modules/core/src/common}/vixen/hw/atapi/cmds/proto_nondata.cpp (96%) create mode 100644 modules/core/src/common/vixen/hw/basic/char.cpp rename {src/core => modules/core/src/common}/vixen/hw/basic/char_null.cpp (93%) rename {src/core => modules/core/src/common}/vixen/hw/basic/cmos.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/basic/gsi.cpp (90%) rename {src/core => modules/core/src/common}/vixen/hw/basic/i8254.cpp (98%) rename {src/core => modules/core/src/common}/vixen/hw/basic/i8259.cpp (98%) rename {src/core => modules/core/src/common}/vixen/hw/basic/irq.cpp (88%) rename {src/core => modules/core/src/common}/vixen/hw/basic/mcpx.cpp (89%) rename {src/core => modules/core/src/common}/vixen/hw/basic/serial.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/basic/superio.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/bus/isabus.cpp (97%) rename {src/core => modules/core/src/common}/vixen/hw/bus/pcibus.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/bus/smbus.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/ohci/ohci.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/ohci/ohci_hub.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/pci/ac97.cpp (98%) rename {src/core => modules/core/src/common}/vixen/hw/pci/agpbridge.cpp (97%) rename {src/core => modules/core/src/common}/vixen/hw/pci/bmide.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/pci/bmide_channel.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/pci/hostbridge.cpp (98%) rename {src/core => modules/core/src/common}/vixen/hw/pci/lpc.cpp (98%) rename {src/core => modules/core/src/common}/vixen/hw/pci/mcpx_ram.cpp (94%) rename {src/core => modules/core/src/common}/vixen/hw/pci/nv2a.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/pci/nvapu.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/pci/nvnet.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/pci/pci.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/pci/pci_irq.cpp (89%) rename {src/core => modules/core/src/common}/vixen/hw/pci/pcibridge.cpp (98%) rename {src/core => modules/core/src/common}/vixen/hw/pci/usb_pci.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/sm/adm1032.cpp (96%) rename {src/core => modules/core/src/common}/vixen/hw/sm/eeprom.cpp (96%) create mode 100644 modules/core/src/common/vixen/hw/sm/sm.cpp rename {src/core => modules/core/src/common}/vixen/hw/sm/smc.cpp (99%) rename {src/core => modules/core/src/common}/vixen/hw/sm/tvenc.cpp (96%) rename {src/core => modules/core/src/common}/vixen/hw/sm/tvenc_conexant.cpp (96%) rename {src/core => modules/core/src/common}/vixen/hw/xid/xid_gamepad.cpp (99%) rename {src => modules/core/src}/common/vixen/io.cpp (99%) rename {src => modules/core/src}/common/vixen/iovec.cpp (99%) rename {src => modules/core/src}/common/vixen/log.cpp (92%) rename {src/core => modules/core/src/common}/vixen/timer.cpp (94%) create mode 100644 modules/core/src/common/vixen/util/fifo.cpp rename {src/core => modules/core/src/common}/vixen/util/invoke_later.cpp (97%) rename {src/core => modules/core/src/common}/vixen/xbox.cpp (80%) rename {src/common/vixen => modules/core/src}/linux/thread.cpp (100%) rename {src/common/vixen/win32 => modules/core/src/windows}/thread.cpp (100%) rename {src/core => modules/core/src/windows}/vixen/hw/basic/win32/char_serial.cpp (100%) rename {src/core => modules/core/src/windows}/vixen/hw/basic/win32/char_serial.h (95%) rename {src/core => modules/core/src/windows}/vixen/hw/basic/win32/mt_serial.cpp (100%) rename {src/core => modules/core/src/windows}/vixen/hw/basic/win32/mt_serial.h (100%) delete mode 100644 src/cli/CMakeLists.txt delete mode 100644 src/cli/lib/CMakeLists.txt delete mode 100644 src/common/CMakeLists.txt delete mode 100644 src/common/vixen/bitmap.h delete mode 100644 src/common/vixen/gdt.cpp delete mode 100644 src/common/vixen/gdt.h delete mode 100644 src/common/vixen/idt.cpp delete mode 100644 src/common/vixen/idt.h delete mode 100644 src/common/vixen/linux/CMakeLists.txt delete mode 100644 src/common/vixen/linux/shlibrary.cpp delete mode 100644 src/common/vixen/memregion.h delete mode 100644 src/common/vixen/platform.h delete mode 100644 src/common/vixen/pte.h delete mode 100644 src/common/vixen/shlibrary.cpp delete mode 100644 src/common/vixen/shlibrary.h delete mode 100644 src/common/vixen/status.h delete mode 100644 src/common/vixen/win32/CMakeLists.txt delete mode 100644 src/common/vixen/win32/shlibrary.cpp delete mode 100644 src/core/CMakeLists.txt delete mode 100644 src/core/vixen/.gitignore delete mode 100644 src/core/vixen/debug.cpp delete mode 100644 src/core/vixen/debug.h delete mode 100644 src/core/vixen/dev.cpp delete mode 100644 src/core/vixen/dev.h delete mode 100644 src/core/vixen/emulator.h delete mode 100644 src/core/vixen/hw/CMakeLists.txt delete mode 100644 src/core/vixen/hw/basic/char.cpp delete mode 100644 src/core/vixen/hw/basic/win32/CMakeLists.txt delete mode 100644 src/core/vixen/hw/sm/sm.cpp delete mode 100644 src/core/vixen/memregion.cpp delete mode 100644 src/core/vixen/module.cpp delete mode 100644 src/core/vixen/module.h delete mode 100644 src/core/vixen/util/CMakeLists.txt delete mode 100644 src/core/vixen/util/fifo.cpp delete mode 100644 src/core/vixen/xbe.cpp delete mode 100644 src/core/vixen/xbe.h delete mode 100644 src/cpu-module-haxm/CMakeLists.txt delete mode 100644 src/cpu-module-haxm/cpu_haxm.cpp delete mode 100644 src/cpu-module-haxm/cpu_haxm.h delete mode 100644 src/cpu-module-haxm/cpu_haxm_module.cpp delete mode 100644 src/cpu-module-haxm/cpu_haxm_module.h delete mode 100644 src/cpu-module-haxm/haxm/darwin/hax_interface_mac.h delete mode 100644 src/cpu-module-haxm/haxm/darwin/hax_types_mac.h delete mode 100644 src/cpu-module-haxm/haxm/hax_interface.h delete mode 100644 src/cpu-module-haxm/haxm/hax_types.h delete mode 100644 src/cpu-module-haxm/haxm/haxm.cpp delete mode 100644 src/cpu-module-haxm/haxm/haxm.h delete mode 100644 src/cpu-module-haxm/haxm/linux/hax_interface_linux.h delete mode 100644 src/cpu-module-haxm/haxm/linux/hax_types_linux.h delete mode 100644 src/cpu-module-haxm/haxm/vcpu_state.h delete mode 100644 src/cpu-module-haxm/haxm/windows/hax_interface_windows.h delete mode 100644 src/cpu-module-haxm/haxm/windows/hax_types_windows.h delete mode 100644 src/cpu-module-kvm/CMakeLists.txt delete mode 100644 src/cpu-module-kvm/cpu_kvm.cpp delete mode 100644 src/cpu-module-kvm/cpu_kvm.h delete mode 100644 src/cpu-module-kvm/cpu_kvm_module.cpp delete mode 100644 src/cpu-module-kvm/cpu_kvm_module.h delete mode 100644 src/cpu-module-kvm/kvm/kvm.cpp delete mode 100644 src/cpu-module-kvm/kvm/kvm.h delete mode 100644 src/cpu-module-whvp/CMakeLists.txt delete mode 100644 src/cpu-module-whvp/cpu_whvp.cpp delete mode 100644 src/cpu-module-whvp/cpu_whvp.h delete mode 100644 src/cpu-module-whvp/cpu_whvp_module.cpp delete mode 100644 src/cpu-module-whvp/cpu_whvp_module.h delete mode 100644 src/cpu-module-whvp/whvp/whvp.cpp delete mode 100644 src/cpu-module-whvp/whvp/whvp.h delete mode 100644 src/cpu-module/CMakeLists.txt delete mode 100644 src/cpu-module/vixen/cpu.cpp delete mode 100644 src/cpu-module/vixen/cpu.h delete mode 100644 src/cpu-module/vixen/cpu_module.h delete mode 100644 src/cpu-module/vixen/cpu_module_decl.h delete mode 100644 src/module-common/CMakeLists.txt delete mode 100644 src/module-common/vixen/module_common.cpp delete mode 100644 src/module-common/vixen/module_common.h diff --git a/.gitignore b/.gitignore index f3830eb..7dbcfdf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,41 @@ -*.pyc -.DS_Store -build -.vs -cmake-build-debug \ No newline at end of file +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# Visual Studio files +.vs/ + +# CMake build folder +build/ + +# CLion project metadata +.idea/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e3a30b..b05b660 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,55 +1,56 @@ -if(MSVC) - cmake_minimum_required (VERSION 3.8) -else() - cmake_minimum_required (VERSION 3.1) -endif() +# Top-level CMake project definitions. +# ------------------------------------------------------------------------------- +# MIT License +# +# Copyright (c) 2019 Ivan Roberto de Oliveira +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +cmake_minimum_required(VERSION 3.8) + +project(vixen VERSION 1.0.0) # Differentiate between Linux and macOS if(UNIX AND NOT APPLE) - set(LINUX TRUE) + set(LINUX TRUE) endif() -project (vixen) - +# Define properties and include helpers for Visual Studio if(MSVC) - # Set platform names - if("${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)") - set(BUILD_PLATFORM win64) - else() - set(BUILD_PLATFORM win32) - endif() + include(cmake/VSHelpers.cmake) - # Use folders and set the startup project - set_property(GLOBAL PROPERTY USE_FOLDERS ON) - set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT cli) + set_property(GLOBAL PROPERTY USE_FOLDERS ON) + + # Configure startup project + set_property(DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" PROPERTY VS_STARTUP_PROJECT vixen-cli) endif() - -include("${CMAKE_SOURCE_DIR}/cmake/VSHelpers.cmake") +include(cmake/PrecompiledHeader.cmake) +include(GNUInstallDirs) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") # Require C++17 features set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) - -# Set compiler and linker flags except on MSVC -if(NOT MSVC) - add_definitions("-Wall -Werror -O0 -g") -endif() - -# Add viXen projects -add_subdirectory("${CMAKE_SOURCE_DIR}/src/common") -add_subdirectory("${CMAKE_SOURCE_DIR}/src/module-common") -add_subdirectory("${CMAKE_SOURCE_DIR}/src/cpu-module") -if(WIN32) -add_subdirectory("${CMAKE_SOURCE_DIR}/src/cpu-module-haxm") -add_subdirectory("${CMAKE_SOURCE_DIR}/src/cpu-module-whvp") -endif() -if(LINUX) -add_subdirectory("${CMAKE_SOURCE_DIR}/src/cpu-module-kvm") -endif() -add_subdirectory("${CMAKE_SOURCE_DIR}/src/core") -add_subdirectory("${CMAKE_SOURCE_DIR}/src/cli") +set(CMAKE_CXX_EXTENSIONS ON) +# Add modules and apps +add_subdirectory(modules) +add_subdirectory(apps) diff --git a/README.md b/README.md index 537124b..a4bfb4a 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,9 @@ will come later in viXen. The current state of this thing is just a tad bit more tangible than vaporware. Essentially right now it just initializes an x86 system (courtesy of one of the -various virtualization platforms supported by the emulator) and runs whatever -is in ROM, which is provided by the user. +various virtualization platforms supported by +[virt86](https://github.com/StrikerX3/virt86)) and runs whatever is in ROM, +which is provided by the user. If provided with a particular BIOS ROM and a raw hard disk image containing the Microsoft Xbox Dashboard, it will load the Dashboard software succesfully. It @@ -33,65 +34,33 @@ incomplete, incorrect or straight up copies of illegally obtained code. How to Build ------------ viXen uses [CMake](https://cmake.org/) build files to generate projects for -your preferred development platform. viXen contains multiple modules, as -described in the [Project Structure](#project-structure) section below. - -You will need to specify a CPU module for viXen to run. The CMake option -`CPU_MODULE` gives you a choice of default modules bundled with viXen that -can be used for development and release builds. +your preferred development platform. You'll need CMake 3.8 or later. ### Windows -You'll need CMake 3.8 or later and [Visual Studio Community 2017](https://www.visualstudio.com/downloads/). - -Your choices of CPU modules for this platform are: -- `haxm`: [Intel HAXM](https://software.intel.com/en-us/articles/intel-hardware-accelerated-execution-manager-intel-haxm). -Requires an Intel processor with VT-x and runs on any version of Windows. -- `whvp`: [Windows Hypervisor Platform](https://docs.microsoft.com/en-us/virtualization/api/). -Requires Windows 10 Pro with the [April 2018 Update](https://support.microsoft.com/en-us/help/4028685/windows-10-get-the-update) -or later. You'll also need to go to the Windows Features panel and enable the -Windows Hypervisor Platform feature. Note that in doing so, you'll be unable to -use any other virtualization platform (such as VirtualBox, VMware Player or -HAXM). Disable the feature if you wish to continue using those platforms. Note -that WHPX still doesn't work correctly, see issue [#2](https://github.com/StrikerX3/viXen/issues/2). +To make a [Visual Studio 2017](https://www.visualstudio.com/downloads/) +project: ``` > mkdir build > cd build -> cmake -G "Visual Studio 15 2017" .. -DCPU_MODULE= # for 32-bit builds -> cmake -G "Visual Studio 15 2017 Win64" .. -DCPU_MODULE= # for 64-bit builds +> cmake -G "Visual Studio 15 2017" -A Win32 .. # for 32-bit builds +> cmake -G "Visual Studio 15 2017" -A x64 .. # for 64-bit builds ``` The .sln file will be generated in the build folder, ready to build. ### Linux -You'll need CMake 3.1 or later. The Linux build uses [KVM](https://www.linux-kvm.org/page/Main_Page). ``` $ sudo apt-get install cmake $ mkdir build; cd build -$ cmake .. -DCPU_MODULE=kvm && make +$ cmake .. && make $ cd src/cli $ ./vixen-cli -m -b -d -r [debug|retail] ``` ### macOS macOS is currently unsupported. Feel free to submit a pull request to add -support for this platform! (See issue [#3](https://github.com/StrikerX3/viXen/issues/3) -for the Hypervisor.Framework or issue [#17](https://github.com/StrikerX3/viXen/issues/17) -for HAXM) - -Project Structure ------------------ -viXen is split into multiple modules: -- `core`: the core of the emulator, providing basic emulation logic and a -module interface for the various pieces of hardware that composes the Xbox. -This is a static library meant to be used by front-end engines. -- `cli`: a command line front-end for viXen. -- `common`: common code shared across all modules. -- `module-common`: contains common definitions and types for viXen modules. -- `cpu-module`: defines the interface and basic types for CPU modules. -- `cpu-module-haxm`: Windows-only CPU module implementation using [Intel HAXM](https://github.com/intel/haxm). -- `cpu-module-whvp`: Windows-only CPU module implementation using the [Windows Hypervisor Platform](https://docs.microsoft.com/en-us/virtualization/api/). -- `cpu-module-kvm`: Linux-only CPU module implementation using [KVM](https://www.kernel.org/doc/Documentation/virtual/kvm/api.txt) +support for this platform! Debugging Guest Code -------------------- diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt new file mode 100644 index 0000000..844c4e9 --- /dev/null +++ b/apps/CMakeLists.txt @@ -0,0 +1,2 @@ +# Add apps +add_subdirectory(cli) diff --git a/apps/cli/CMakeLists.txt b/apps/cli/CMakeLists.txt new file mode 100644 index 0000000..b7c05e0 --- /dev/null +++ b/apps/cli/CMakeLists.txt @@ -0,0 +1,54 @@ +project(vixen-cli VERSION 1.0.0 LANGUAGES CXX) + +############################## +# Source files +# +file(GLOB_RECURSE sources + src/*.cpp +) + +file(GLOB_RECURSE private_headers + src/*.hpp + src/*.h +) + +file(GLOB_RECURSE public_headers + include/*.hpp + include/*.h +) + +############################## +# Project structure +# +add_executable(vixen-cli ${sources} ${private_headers} ${public_headers}) + +target_include_directories(vixen-cli + PUBLIC + $ + $ + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src +) +target_link_libraries(vixen-cli vixen-core) + +if(MSVC) + add_precompiled_header(vixen-cli pch.hpp SOURCE_CXX "${CMAKE_CURRENT_SOURCE_DIR}/src/pch.cpp" FORCEINCLUDE) + + vs_set_filters(BASE_DIR src FILTER_ROOT "Sources" SOURCES ${sources}) + vs_set_filters(BASE_DIR src FILTER_ROOT "Private Headers" SOURCES ${private_headers}) + vs_set_filters(BASE_DIR include FILTER_ROOT "Public Headers" SOURCES ${public_headers}) + + vs_use_edit_and_continue() + + set_target_properties(vixen-cli PROPERTIES FOLDER Applications) +else() + add_precompiled_header(vixen-cli src/pch.hpp PCH_PATH pch.hpp SOURCE_CXX "${CMAKE_CURRENT_SOURCE_DIR}/src/pch.cpp" FORCEINCLUDE) +endif() + +############################## +# Installation +# +install(TARGETS vixen-cli + EXPORT platform-check + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" +) diff --git a/src/cli/lib/cxxopts.hpp b/apps/cli/src/lib/cxxopts.hpp similarity index 100% rename from src/cli/lib/cxxopts.hpp rename to apps/cli/src/lib/cxxopts.hpp diff --git a/src/cli/main.cpp b/apps/cli/src/main.cpp similarity index 81% rename from src/cli/main.cpp rename to apps/cli/src/main.cpp index dfa4646..85eac17 100644 --- a/src/cli/main.cpp +++ b/apps/cli/src/main.cpp @@ -2,12 +2,15 @@ #include #include #include + #include "lib/cxxopts.hpp" #include "vixen/core.h" #include "vixen/settings.h" #include "vixen/thread.h" +using namespace virt86; + #ifdef _WIN32 char *basename(char *path) { @@ -73,31 +76,29 @@ int main(int argc, const char *argv[]) { vdvd_path = args["xgd-image"].as().c_str(); } - // Locate and instantiate modules - ModuleRepository moduleRepo; - moduleRepo.Enumerate(); + // Pick the first hypervisor platform that is available and properly initialized on this system. + printf("Loading virtualization platforms... "); - // Search for CPU modules - auto cpuModules = moduleRepo.GetCPUModules(); - if (cpuModules.size() == 0) { - log_fatal("No CPU modules found\n"); + bool foundPlatform = false; + size_t platformIndex = 0; + for (size_t i = 0; i < ARRAYSIZE(PlatformFactories); i++) { + Platform& platform = PlatformFactories[i](); + if (platform.GetInitStatus() == PlatformInitStatus::OK) { + printf("%s loaded successfully\n", platform.GetName().c_str()); + foundPlatform = true; + platformIndex = i; + break; + } + } + + if (!foundPlatform) { + printf("none found\n"); return -1; } - // Load first CPU module found - auto cpuModuleInfo = cpuModules[0]; + Platform& platform = PlatformFactories[platformIndex](); - // Instantiate CPU module - log_info("Loading CPU module: %s %s... ", cpuModuleInfo.moduleName.c_str(), cpuModuleInfo.moduleVersion.c_str()); - CPUModuleInstance cpuModuleInstance; - auto cpuModuleResult = LoadCPUModule(cpuModuleInfo.libraryPath, &cpuModuleInstance); - if (cpuModuleResult != kModuleLoadSuccess) { - log_fatal("instantiation failed; result code 0x%x\n", cpuModuleResult); - return -1; - } - log_info("success\n"); - - Xbox *xbox = new Xbox(cpuModuleInstance.cpuModule); + Xbox *xbox = new Xbox(platform); auto& settings = xbox->GetSettings(); settings.cpu_singleStep = false; @@ -158,7 +159,7 @@ int main(int argc, const char *argv[]) { log_fatal("Emulator exited with error: "); switch (status) { case EMUS_INIT_INVALID_REVISION: log_fatal("Invalid revision specified\n"); break; - case EMUS_INIT_ALLOC_MEM_RGN_FAILED: log_fatal("Could not allocate memory for the global memory region\n"); break; + case EMUS_INIT_VM_INIT_FAILED: log_fatal("Failed to initialize virtual machine\n"); break; case EMUS_INIT_ALLOC_RAM_FAILED: log_fatal("Could not allocate memory for the guest RAM\n"); break; case EMUS_INIT_ALLOC_RAM_RGN_FAILED: log_fatal("Could not allocate memory for the RAM region"); break; case EMUS_INIT_ALLOC_ROM_FAILED: log_fatal("Could not allocate memory for the guest ROM"); break; @@ -167,10 +168,6 @@ int main(int argc, const char *argv[]) { case EMUS_INIT_MCPX_ROM_INVALID_SIZE: log_fatal("MCPX ROM provided has incorrect size (must be 512 bytes)"); break; case EMUS_INIT_BIOS_ROM_NOT_FOUND: log_fatal("BIOS ROM file not found"); break; case EMUS_INIT_BIOS_ROM_INVALID_SIZE: log_fatal("BIOS ROM provided has incorrect size (must be 256 KiB or 1 MiB)"); break; - case EMUS_INIT_NO_CPU_MODULE: log_fatal("No CPU module specified"); break; - case EMUS_INIT_CPU_CREATE_FAILED: log_fatal("CPU instantiation failed"); break; - case EMUS_INIT_CPU_INIT_FAILED: log_fatal("CPU initialization failed"); break; - case EMUS_INIT_CPU_MEM_MAP_FAILED: log_fatal("Memory mapping failed"); break; case EMUS_INIT_INVALID_HARD_DRIVE_TYPE: log_fatal("Invalid virtual hard drive type specified"); break; case EMUS_INIT_HARD_DRIVE_INIT_FAILED: log_fatal("Failed to initialize virtual hard drive"); break; case EMUS_INIT_INVALID_DVD_DRIVE_TYPE: log_fatal("Invalid virtual DVD drive type specified"); break; diff --git a/apps/cli/src/pch.cpp b/apps/cli/src/pch.cpp new file mode 100644 index 0000000..253c32b --- /dev/null +++ b/apps/cli/src/pch.cpp @@ -0,0 +1,26 @@ +/* +This file is required by Visual Studio in order to compile pch.hpp. +------------------------------------------------------------------------------- +MIT License + +Copyright (c) 2019 Ivan Roberto de Oliveira + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#include "pch.hpp" diff --git a/apps/cli/src/pch.hpp b/apps/cli/src/pch.hpp new file mode 100644 index 0000000..81b9968 --- /dev/null +++ b/apps/cli/src/pch.hpp @@ -0,0 +1,29 @@ +/* +Precompiled header for the Platform Checker application. +------------------------------------------------------------------------------- +MIT License + +Copyright (c) 2019 Ivan Roberto de Oliveira + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#include +#include + +#include "virt86/virt86.hpp" diff --git a/cmake/PrecompiledHeader.cmake b/cmake/PrecompiledHeader.cmake index 903df83..379e9df 100644 --- a/cmake/PrecompiledHeader.cmake +++ b/cmake/PrecompiledHeader.cmake @@ -63,20 +63,136 @@ macro(combine_arguments _variable) set(${_variable} "${_result}") endmacro() -function(export_all_flags _filename) +function(export_all_flags _filename mode) + get_target_property(_target_type ${_target} TYPE) + if(_target_type STREQUAL "EXECUTABLE") + set(_pic "$<$>:-fPIE\n>") + else() + set(_pic "$<$>:-fPIC\n>") + endif() + set(_include_directories "$") set(_compile_definitions "$") set(_compile_flags "$") set(_compile_options "$") - set(_include_directories "$<$:-I$\n>") + set(_include_directories "$<$:-I\"$\"\n>") set(_compile_definitions "$<$:-D$\n>") set(_compile_flags "$<$:$\n>") set(_compile_options "$<$:$\n>") - file(GENERATE OUTPUT "${_filename}" CONTENT "${_compile_definitions}${_include_directories}${_compile_flags}${_compile_options}\n") + + set(_standard_check "") + if("${mode}" STREQUAL "CXX") + set(_cxx_standard "$") + set(_cxx_extensions "$") + set(_has_extensions "$,$>") # CXX_EXTENSIONS defaults to true + set(_standard_check "${_standard_check}$<$,$>:${CMAKE_CXX17_STANDARD_COMPILE_OPTION}>") + set(_standard_check "${_standard_check}$<$,$>:${CMAKE_CXX14_STANDARD_COMPILE_OPTION}>") + set(_standard_check "${_standard_check}$<$,$>:${CMAKE_CXX11_STANDARD_COMPILE_OPTION}>") + set(_standard_check "${_standard_check}$<$,$>:${CMAKE_CXX98_STANDARD_COMPILE_OPTION}>") + set(_standard_check "${_standard_check}$<$,${_has_extensions}>:${CMAKE_CXX17_EXTENSION_COMPILE_OPTION}>") + set(_standard_check "${_standard_check}$<$,${_has_extensions}>:${CMAKE_CXX14_EXTENSION_COMPILE_OPTION}>") + set(_standard_check "${_standard_check}$<$,${_has_extensions}>:${CMAKE_CXX11_EXTENSION_COMPILE_OPTION}>") + set(_standard_check "${_standard_check}$<$,${_has_extensions}>:${CMAKE_CXX98_EXTENSION_COMPILE_OPTION}>") + endif() + if("${mode}" STREQUAL "C") + set(_c_standard "$") + set(_c_extensions "$") + set(_has_extensions "$,$>") # C_EXTENSIONS defaults to true + set(_standard_check "${_standard_check}$<$,$>:${CMAKE_C11_STANDARD_COMPILE_OPTION}>") + set(_standard_check "${_standard_check}$<$,$>:${CMAKE_C99_STANDARD_COMPILE_OPTION}>") + set(_standard_check "${_standard_check}$<$,$>:${CMAKE_C90_STANDARD_COMPILE_OPTION}>") + set(_standard_check "${_standard_check}$<$,${_has_extensions}>:${CMAKE_C11_EXTENSION_COMPILE_OPTION}>") + set(_standard_check "${_standard_check}$<$,${_has_extensions}>:${CMAKE_C99_EXTENSION_COMPILE_OPTION}>") + set(_standard_check "${_standard_check}$<$,${_has_extensions}>:${CMAKE_C90_EXTENSION_COMPILE_OPTION}>") + endif() + set(_standard_check "${_standard_check}\n") + + file(GENERATE OUTPUT "${_filename}" CONTENT "${_compile_definitions}${_include_directories}${_compile_flags}${_compile_options}${_standard_check}${_pic}\n") +endfunction() + +function (gcc_pch_targets_for_mode _input _pch_path mode) + get_filename_component(_name ${_input} NAME) + set(_pch_header "${CMAKE_CURRENT_SOURCE_DIR}/${_input}") + set(_pch_binary_dir "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${mode}_pch") + set(_pchfile "${_pch_binary_dir}/${_input}") + + string(REGEX MATCH "\.\.[/\\]" _has_parent_access "${_input}") + if( "${_pch_path}" STREQUAL "" AND _has_parent_access) + message(FATAL_ERROR "Precompiled header name contains ../, please specify an outputh path with the PCH_PATH option") + endif() + + if( NOT "${_pch_path}" STREQUAL "" ) + set(_pchfile "${_pch_binary_dir}/${_pch_path}") + endif() + set(_output "${_pch_binary_dir}/${_input}.gch") + if( NOT "${_pch_path}" STREQUAL "" ) + set(_output "${_pch_binary_dir}/${_pch_path}.gch") + endif() + + set(_pch_flags_file "${_pch_binary_dir}/compile_flags.rsp") + export_all_flags("${_pch_flags_file}" ${mode}) + set(_compiler_FLAGS "@${_pch_flags_file}") + add_custom_command( + OUTPUT "${_pchfile}" + COMMAND "${CMAKE_COMMAND}" -E copy "${_pch_header}" "${_pchfile}" + DEPENDS "${_pch_header}" + COMMENT "Updating ${_name} (${mode})") + if("${mode}" STREQUAL "CXX") + add_custom_command( + OUTPUT "${_output}" + COMMAND "${CMAKE_CXX_COMPILER}" ${_compiler_FLAGS} -x c++-header -o "${_output}" "${_pchfile}" + DEPENDS "${_pchfile}" "${_pch_flags_file}" + COMMENT "Precompiling ${_name} for ${_target} (C++)") + endif() + if("${mode}" STREQUAL "C") + add_custom_command( + OUTPUT "${_output}" + COMMAND "${CMAKE_C_COMPILER}" ${_compiler_FLAGS_c} -x c-header -o "${_output}" "${_pchfile}" + DEPENDS "${_pchfile}" "${_pch_flags_file}" + COMMENT "Precompiling ${_name} for ${_target} (C)") + endif() + + set(_extensions "") + if("${mode}" STREQUAL "CXX") + set(_extensions "cc|cxx|cpp") + endif() + if("${mode}" STREQUAL "C") + set(_extensions "c") + endif() + + get_property(_sources TARGET ${_target} PROPERTY SOURCES) + foreach(_source ${_sources}) + set(_pch_compile_flags "") + if(_source MATCHES \\.\(${_extensions}\)$) + get_source_file_property(_pch_compile_flags "${_source}" COMPILE_FLAGS) + if(NOT _pch_compile_flags) + set(_pch_compile_flags) + endif() + separate_arguments(_pch_compile_flags) + list(APPEND _pch_compile_flags -Winvalid-pch) + if(_PCH_FORCEINCLUDE) + list(APPEND _pch_compile_flags -include "${_pchfile}") + else(_PCH_FORCEINCLUDE) + list(APPEND _pch_compile_flags "-I${_pch_binary_dir}") + endif(_PCH_FORCEINCLUDE) + + get_source_file_property(_object_depends "${_source}" OBJECT_DEPENDS) + if(NOT _object_depends) + set(_object_depends) + endif() + list(APPEND _object_depends "${_pchfile}") + list(APPEND _object_depends "${_output}") + + combine_arguments(_pch_compile_flags) + set_source_files_properties(${_source} PROPERTIES + COMPILE_FLAGS "${_pch_compile_flags}" + OBJECT_DEPENDS "${_object_depends}") + endif() + endforeach() endfunction() function(add_precompiled_header _target _input) - cmake_parse_arguments(_PCH "FORCEINCLUDE" "SOURCE_CXX;SOURCE_C" "" ${ARGN}) + cmake_parse_arguments(_PCH "FORCEINCLUDE" "SOURCE_CXX;SOURCE_C;PCH_PATH" "" ${ARGN}) get_filename_component(_input_we ${_input} NAME_WE) if(NOT _PCH_SOURCE_CXX) @@ -147,77 +263,17 @@ function(add_precompiled_header _target _input) endif() endif(MSVC) - if(CMAKE_COMPILER_IS_GNUCXX) - get_filename_component(_name ${_input} NAME) - set(_pch_header "${CMAKE_CURRENT_SOURCE_DIR}/${_input}") - set(_pch_binary_dir "${CMAKE_CURRENT_BINARY_DIR}/${_target}_pch") - set(_pchfile "${_pch_binary_dir}/${_input}") - set(_outdir "${CMAKE_CURRENT_BINARY_DIR}/${_target}_pch/${_name}.gch") - file(MAKE_DIRECTORY "${_outdir}") - set(_output_cxx "${_outdir}/.c++") - set(_output_c "${_outdir}/.c") - - set(_pch_flags_file "${_pch_binary_dir}/compile_flags.rsp") - export_all_flags("${_pch_flags_file}") - set(_compiler_FLAGS "@${_pch_flags_file}") - if(CMAKE_CXX_STANDARD STREQUAL 11) - set(_compiler_FLAGS "${_compiler_FLAGS}" "-std=c++11") + if(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") + # Clang only uses PCHs when using the -include option + # See: https://clang.llvm.org/docs/UsersManual.html#using-a-pch-file + if(NOT _PCH_FORCEINCLUDE) + message(WARNING "Clang requires the FORCEINCLUDE option to use PCHs, turning it on") endif() - if(CMAKE_CXX_STANDARD STREQUAL 14) - set(_compiler_FLAGS "${_compiler_FLAGS}" "-std=c++14") - endif() - if(CMAKE_CXX_STANDARD STREQUAL 17) - set(_compiler_FLAGS "${_compiler_FLAGS}" "-std=c++17") - endif() - add_custom_command( - OUTPUT "${_pchfile}" - COMMAND "${CMAKE_COMMAND}" -E copy "${_pch_header}" "${_pchfile}" - DEPENDS "${_pch_header}" - COMMENT "Updating ${_name}") - add_custom_command( - OUTPUT "${_output_cxx}" - COMMAND "${CMAKE_CXX_COMPILER}" ${_compiler_FLAGS} -x c++-header -o "${_output_cxx}" "${_pchfile}" - DEPENDS "${_pchfile}" "${_pch_flags_file}" - COMMENT "Precompiling ${_name} for ${_target} (C++)") - add_custom_command( - OUTPUT "${_output_c}" - COMMAND "${CMAKE_C_COMPILER}" ${_compiler_FLAGS} -x c-header -o "${_output_c}" "${_pchfile}" - DEPENDS "${_pchfile}" "${_pch_flags_file}" - COMMENT "Precompiling ${_name} for ${_target} (C)") + set(_PCH_FORCEINCLUDE ON) + endif() - get_property(_sources TARGET ${_target} PROPERTY SOURCES) - foreach(_source ${_sources}) - set(_pch_compile_flags "") - - if(_source MATCHES \\.\(cc|cxx|cpp|c\)$) - get_source_file_property(_pch_compile_flags "${_source}" COMPILE_FLAGS) - if(NOT _pch_compile_flags) - set(_pch_compile_flags) - endif() - separate_arguments(_pch_compile_flags) - list(APPEND _pch_compile_flags -Winvalid-pch) - if(_PCH_FORCEINCLUDE) - list(APPEND _pch_compile_flags -include "${_pchfile}") - else(_PCH_FORCEINCLUDE) - list(APPEND _pch_compile_flags "-I${_pch_binary_dir}") - endif(_PCH_FORCEINCLUDE) - - get_source_file_property(_object_depends "${_source}" OBJECT_DEPENDS) - if(NOT _object_depends) - set(_object_depends) - endif() - list(APPEND _object_depends "${_pchfile}") - if(_source MATCHES \\.\(cc|cxx|cpp\)$) - list(APPEND _object_depends "${_output_cxx}") - else() - list(APPEND _object_depends "${_output_c}") - endif() - - combine_arguments(_pch_compile_flags) - set_source_files_properties(${_source} PROPERTIES - COMPILE_FLAGS "${_pch_compile_flags}" - OBJECT_DEPENDS "${_object_depends}") - endif() - endforeach() - endif(CMAKE_COMPILER_IS_GNUCXX) + if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU|Clang") + gcc_pch_targets_for_mode("${_input}" "${_PCH_PCH_PATH}" "C") + gcc_pch_targets_for_mode("${_input}" "${_PCH_PCH_PATH}" "CXX") + endif(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU|Clang") endfunction() diff --git a/cmake/VSHelpers.cmake b/cmake/VSHelpers.cmake index bb498a0..dce70ae 100644 --- a/cmake/VSHelpers.cmake +++ b/cmake/VSHelpers.cmake @@ -1,16 +1,8 @@ # Add Visual Studio filters to better organize the code -function(vs_set_filters SOURCES) +function(vs_set_filters) + cmake_parse_arguments(VS_SET_FILTERS "" "FILTER_ROOT;BASE_DIR" "SOURCES" ${ARGN}) if(MSVC) - set(extra_macro_args ${ARGN}) - list(LENGTH extra_macro_args num_extra_args) - if(${num_extra_args} GREATER 0) - list(GET extra_macro_args 0 optional_arg) - set(BASE_DIR "${optional_arg}") - else() - set(BASE_DIR "") - endif() - - foreach(FILE ${SOURCES}) + foreach(FILE IN ITEMS ${VS_SET_FILTERS_SOURCES}) # Get the directory of the source file get_filename_component(PARENT_DIR "${FILE}" DIRECTORY) @@ -18,20 +10,14 @@ function(vs_set_filters SOURCES) if(BASE_DIR STREQUAL "") string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" "" GROUP "${PARENT_DIR}") else() - string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/${BASE_DIR}" "" GROUP "${PARENT_DIR}") + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/${VS_SET_FILTERS_BASE_DIR}" "" GROUP "${PARENT_DIR}") endif() - # Make sure we are using windows slashes + # Use Windows path separators string(REPLACE "/" "\\" GROUP "${GROUP}") - # Group into "Source Files" and "Header Files" - if("${FILE}" MATCHES ".*\\.c(pp)?") - set(GROUP "Source Files${GROUP}") - elseif("${FILE}" MATCHES ".*\\.h") - set(GROUP "Header Files${GROUP}") - endif() - - source_group("${GROUP}" FILES "${FILE}") + # Add to filter + source_group("${VS_SET_FILTERS_FILTER_ROOT}${GROUP}" FILES "${FILE}") endforeach() endif() endfunction() diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt new file mode 100644 index 0000000..78c8003 --- /dev/null +++ b/modules/CMakeLists.txt @@ -0,0 +1,2 @@ +# Add modules +add_subdirectory(core) diff --git a/modules/core/CMakeLists.txt b/modules/core/CMakeLists.txt new file mode 100644 index 0000000..19288f7 --- /dev/null +++ b/modules/core/CMakeLists.txt @@ -0,0 +1,173 @@ +# The core of the viXen emulator. +# ------------------------------------------------------------------------------- +# MIT License +# +# Copyright (c) 2019 Ivan Roberto de Oliveira +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +project(vixen-core VERSION 1.0.0 LANGUAGES CXX) + +include(ExternalProject) + +############################## +# Source files +# +if(WIN32) + set(platform_path windows) +elseif(LINUX) + set(platform_path linux) +elseif(APPLE) + set(platform_path darwin) +else() + message(FATAL_ERROR "Unsupported platform") +endif() + +file(GLOB_RECURSE sources + src/common/*.cpp + src/${platform_path}/*.cpp + src/pch.cpp +) + +file(GLOB_RECURSE private_headers + src/common/*.hpp + src/common/*.h + src/${platform_path}/*.hpp + src/${platform_path}/*.h + src/pch.hpp +) + +file(GLOB_RECURSE public_headers + include/*.hpp + include/*.h +) + +############################## +# Project structure +# + +add_library(vixen-core OBJECT ${sources} ${private_headers} ${public_headers}) + +set_target_properties(vixen-core PROPERTIES DEBUG_POSTFIX "-debug") + +target_include_directories(vixen-core + PUBLIC + $ + $ + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src/common + ${CMAKE_CURRENT_SOURCE_DIR}/src/${platform_path} +) + +# Include virt86 +find_package(virt86 CONFIG REQUIRED) +target_link_libraries(vixen-core PUBLIC virt86::virt86) + +# TODO: Include Zydis +# add_definitions(-DZYDIS_STATIC_DEFINE) +# ExternalProject_Add( +# Zydis +# GIT_REPOSITORY "https://github.com/zyantific/zydis" +# GIT_TAG "v2.0.0" +# UPDATE_COMMAND "" +# INSTALL_COMMAND "") +# ExternalProject_Get_Property(Zydis install_dir) +# target_include_directories(vixen-core PUBLIC ${install_dir}/src/Zydis/include ${install_dir}/src/Zydis-build) +# add_dependencies(vixen-core Zydis) +# +# if(WIN32) +# target_link_libraries(vixen-core PUBLIC ${install_dir}/src/Zydis-build/${CMAKE_CFG_INTDIR}/Zydis.lib) +# else() +# target_link_libraries(vixen-core PUBLIC ${install_dir}/src/Zydis-build/libZydis.a) +# endif() +# +# target_include_directories(vixen-core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${install_dir}/src/Zydis/include) + +if(MSVC) + add_precompiled_header(vixen-core pch.hpp SOURCE_CXX "${CMAKE_CURRENT_SOURCE_DIR}/src/common/pch.cpp" FORCEINCLUDE) + + vs_set_filters(BASE_DIR src FILTER_ROOT "Sources" SOURCES ${sources}) + vs_set_filters(BASE_DIR src FILTER_ROOT "Private Headers" SOURCES ${private_headers}) + vs_set_filters(BASE_DIR include FILTER_ROOT "Public Headers" SOURCES ${public_headers}) + + vs_use_edit_and_continue() + + set_target_properties(vixen-core PROPERTIES FOLDER Libraries) +else() + add_precompiled_header(vixen-core src/common/pch.hpp PCH_PATH pch.hpp SOURCE_CXX "${CMAKE_CURRENT_SOURCE_DIR}/src/common/pch.cpp" FORCEINCLUDE) +endif() + +############################## +# Installation +# + +# Configuration +set(config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") +set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated") +set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake") +set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake") +set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") +set(namespace "vixen::") + +# Include module with function 'write_basic_package_version_file' +include(CMakePackageConfigHelpers) + +# Configure 'ConfigVersion.cmake' +# Use: +# * PROJECT_VERSION +write_basic_package_version_file( + "${version_config}" COMPATIBILITY SameMajorVersion +) + +# Configure 'Config.cmake' +# Use variables: +# * TARGETS_EXPORT_NAME +# * PROJECT_NAME +configure_package_config_file( + "cmake/Config.cmake.in" + "${project_config}" + INSTALL_DESTINATION "${config_install_dir}" +) + +# Install target library +install(TARGETS vixen-core + EXPORT "${TARGETS_EXPORT_NAME}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" +) + +# Install public headers +install(DIRECTORY "include/" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" +) + +# Install CMake Config modules +# * /lib/cmake//Config.cmake +# * /lib/cmake//ConfigVersion.cmake +install(FILES "${project_config}" "${version_config}" + DESTINATION "${config_install_dir}" +) + +# Install CMake Target module +# * /lib/cmake//Targets.cmake +install(EXPORT "${TARGETS_EXPORT_NAME}" + NAMESPACE "${namespace}" + DESTINATION "${config_install_dir}" +) diff --git a/modules/core/cmake/Config.cmake.in b/modules/core/cmake/Config.cmake.in new file mode 100644 index 0000000..a8ce5f4 --- /dev/null +++ b/modules/core/cmake/Config.cmake.in @@ -0,0 +1,27 @@ +# Template for CMake Config module. +# ------------------------------------------------------------------------------- +# MIT License +# +# Copyright (c) 2019 Ivan Roberto de Oliveira +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake") +check_required_components("@PROJECT_NAME@") diff --git a/src/core/vixen/alloc.h b/modules/core/include/vixen/alloc.h similarity index 100% rename from src/core/vixen/alloc.h rename to modules/core/include/vixen/alloc.h diff --git a/src/core/vixen/core.h b/modules/core/include/vixen/core.h similarity index 87% rename from src/core/vixen/core.h rename to modules/core/include/vixen/core.h index 2ece102..09f00b6 100644 --- a/src/core/vixen/core.h +++ b/modules/core/include/vixen/core.h @@ -1,7 +1,6 @@ #pragma once #include "vixen/xbox.h" -#include "vixen/module.h" namespace vixen { diff --git a/src/common/vixen/cxbxtimer.h b/modules/core/include/vixen/cxbxtimer.h similarity index 100% rename from src/common/vixen/cxbxtimer.h rename to modules/core/include/vixen/cxbxtimer.h diff --git a/modules/core/include/vixen/debug.h b/modules/core/include/vixen/debug.h new file mode 100644 index 0000000..ce30cc8 --- /dev/null +++ b/modules/core/include/vixen/debug.h @@ -0,0 +1,29 @@ +#pragma once + +#include "virt86/virt86.hpp" + +#include "vixen/log.h" + +namespace vixen { + +/*! + * Print the CPU registers + */ +void DumpCPURegisters(virt86::VirtualProcessor& vp); + +/*! + * Dump CPU stack + */ +void DumpCPUStack(virt86::VirtualProcessor& vp, int32_t offsetStart = -0x20, int32_t offsetEnd = 0x10); + +/*! + * Dump memory + */ +void DumpCPUMemory(virt86::VirtualProcessor& vp, uint32_t address, uint32_t size, bool physical); + +/*! + * Disassemble memory region + */ +void DumpCPUDisassembly(virt86::VirtualProcessor& vp, uint32_t address, uint32_t size, bool physical); + +} diff --git a/src/common/vixen/dynamic_variant.h b/modules/core/include/vixen/dynamic_variant.h similarity index 100% rename from src/common/vixen/dynamic_variant.h rename to modules/core/include/vixen/dynamic_variant.h diff --git a/src/core/vixen/gdbserver.h b/modules/core/include/vixen/gdbserver.h similarity index 96% rename from src/core/vixen/gdbserver.h rename to modules/core/include/vixen/gdbserver.h index 9c9c9c5..c74621b 100644 --- a/src/core/vixen/gdbserver.h +++ b/modules/core/include/vixen/gdbserver.h @@ -20,7 +20,7 @@ #include #ifdef _WIN32 # define _WIN32_LEAN_AND_MEAN -# include +//# include # include # pragma comment (lib, "ws2_32.lib") #else @@ -36,12 +36,11 @@ #include #include #include -#include "vixen/cpu.h" + +#include "virt86/virt86.hpp" namespace vixen { -using namespace vixen::cpu; - #ifdef _WIN32 typedef int socklen_t; typedef int ssize_t; @@ -86,7 +85,7 @@ typedef int (*dbg_dec_func)(const char *buf, size_t buf_len, char *data, size_t class GdbServer { protected: - Cpu *m_cpu; + virt86::VirtualProcessor& m_vp; const char *m_bind_host; int m_bind_port; struct sockaddr_in m_bind_addr; @@ -137,7 +136,7 @@ protected: int dbg_main(); public: - GdbServer(Cpu *cpu, const char *bind_host, int bind_port); + GdbServer(virt86::VirtualProcessor& vp, const char *bind_host, int bind_port); ~GdbServer(); int Initialize(); int WaitForConnection(); diff --git a/src/core/vixen/hw/ata/ata.h b/modules/core/include/vixen/hw/ata/ata.h similarity index 95% rename from src/core/vixen/hw/ata/ata.h rename to modules/core/include/vixen/hw/ata/ata.h index 41cc0e3..e3d5591 100644 --- a/src/core/vixen/hw/ata/ata.h +++ b/modules/core/include/vixen/hw/ata/ata.h @@ -13,9 +13,9 @@ #include -#include "vixen/cpu.h" #include "../basic/irq.h" -#include "../ata/ata_defs.h" +#include "vixen/io.h" +#include "ata_defs.h" #include "ata_channel.h" namespace vixen { diff --git a/src/core/vixen/hw/ata/ata_channel.h b/modules/core/include/vixen/hw/ata/ata_channel.h similarity index 99% rename from src/core/vixen/hw/ata/ata_channel.h rename to modules/core/include/vixen/hw/ata/ata_channel.h index 351b2f8..2244fe0 100644 --- a/src/core/vixen/hw/ata/ata_channel.h +++ b/modules/core/include/vixen/hw/ata/ata_channel.h @@ -15,7 +15,6 @@ #include -#include "vixen/cpu.h" #include "vixen/dynamic_variant.h" #include "../basic/irq.h" #include "../basic/interrupt.h" diff --git a/src/core/vixen/hw/ata/ata_common.h b/modules/core/include/vixen/hw/ata/ata_common.h similarity index 100% rename from src/core/vixen/hw/ata/ata_common.h rename to modules/core/include/vixen/hw/ata/ata_common.h diff --git a/src/core/vixen/hw/ata/ata_defs.h b/modules/core/include/vixen/hw/ata/ata_defs.h similarity index 100% rename from src/core/vixen/hw/ata/ata_defs.h rename to modules/core/include/vixen/hw/ata/ata_defs.h diff --git a/src/core/vixen/hw/ata/ata_device.h b/modules/core/include/vixen/hw/ata/ata_device.h similarity index 100% rename from src/core/vixen/hw/ata/ata_device.h rename to modules/core/include/vixen/hw/ata/ata_device.h diff --git a/src/core/vixen/hw/ata/cmds/ata_command.h b/modules/core/include/vixen/hw/ata/cmds/ata_command.h similarity index 100% rename from src/core/vixen/hw/ata/cmds/ata_command.h rename to modules/core/include/vixen/hw/ata/cmds/ata_command.h diff --git a/src/core/vixen/hw/ata/cmds/cmd_identify_device.h b/modules/core/include/vixen/hw/ata/cmds/cmd_identify_device.h similarity index 100% rename from src/core/vixen/hw/ata/cmds/cmd_identify_device.h rename to modules/core/include/vixen/hw/ata/cmds/cmd_identify_device.h diff --git a/src/core/vixen/hw/ata/cmds/cmd_identify_packet_device.h b/modules/core/include/vixen/hw/ata/cmds/cmd_identify_packet_device.h similarity index 100% rename from src/core/vixen/hw/ata/cmds/cmd_identify_packet_device.h rename to modules/core/include/vixen/hw/ata/cmds/cmd_identify_packet_device.h diff --git a/src/core/vixen/hw/ata/cmds/cmd_init_dev_params.h b/modules/core/include/vixen/hw/ata/cmds/cmd_init_dev_params.h similarity index 100% rename from src/core/vixen/hw/ata/cmds/cmd_init_dev_params.h rename to modules/core/include/vixen/hw/ata/cmds/cmd_init_dev_params.h diff --git a/src/core/vixen/hw/ata/cmds/cmd_packet.h b/modules/core/include/vixen/hw/ata/cmds/cmd_packet.h similarity index 100% rename from src/core/vixen/hw/ata/cmds/cmd_packet.h rename to modules/core/include/vixen/hw/ata/cmds/cmd_packet.h diff --git a/src/core/vixen/hw/ata/cmds/cmd_read_dma.h b/modules/core/include/vixen/hw/ata/cmds/cmd_read_dma.h similarity index 100% rename from src/core/vixen/hw/ata/cmds/cmd_read_dma.h rename to modules/core/include/vixen/hw/ata/cmds/cmd_read_dma.h diff --git a/src/core/vixen/hw/ata/cmds/cmd_security_unlock.h b/modules/core/include/vixen/hw/ata/cmds/cmd_security_unlock.h similarity index 100% rename from src/core/vixen/hw/ata/cmds/cmd_security_unlock.h rename to modules/core/include/vixen/hw/ata/cmds/cmd_security_unlock.h diff --git a/src/core/vixen/hw/ata/cmds/cmd_set_features.h b/modules/core/include/vixen/hw/ata/cmds/cmd_set_features.h similarity index 100% rename from src/core/vixen/hw/ata/cmds/cmd_set_features.h rename to modules/core/include/vixen/hw/ata/cmds/cmd_set_features.h diff --git a/src/core/vixen/hw/ata/cmds/cmd_write_dma.h b/modules/core/include/vixen/hw/ata/cmds/cmd_write_dma.h similarity index 100% rename from src/core/vixen/hw/ata/cmds/cmd_write_dma.h rename to modules/core/include/vixen/hw/ata/cmds/cmd_write_dma.h diff --git a/src/core/vixen/hw/ata/cmds/proto_dma.h b/modules/core/include/vixen/hw/ata/cmds/proto_dma.h similarity index 100% rename from src/core/vixen/hw/ata/cmds/proto_dma.h rename to modules/core/include/vixen/hw/ata/cmds/proto_dma.h diff --git a/src/core/vixen/hw/ata/cmds/proto_nondata.h b/modules/core/include/vixen/hw/ata/cmds/proto_nondata.h similarity index 100% rename from src/core/vixen/hw/ata/cmds/proto_nondata.h rename to modules/core/include/vixen/hw/ata/cmds/proto_nondata.h diff --git a/src/core/vixen/hw/ata/cmds/proto_packet.h b/modules/core/include/vixen/hw/ata/cmds/proto_packet.h similarity index 100% rename from src/core/vixen/hw/ata/cmds/proto_packet.h rename to modules/core/include/vixen/hw/ata/cmds/proto_packet.h diff --git a/src/core/vixen/hw/ata/cmds/proto_pio_data_in.h b/modules/core/include/vixen/hw/ata/cmds/proto_pio_data_in.h similarity index 100% rename from src/core/vixen/hw/ata/cmds/proto_pio_data_in.h rename to modules/core/include/vixen/hw/ata/cmds/proto_pio_data_in.h diff --git a/src/core/vixen/hw/ata/cmds/proto_pio_data_out.h b/modules/core/include/vixen/hw/ata/cmds/proto_pio_data_out.h similarity index 100% rename from src/core/vixen/hw/ata/cmds/proto_pio_data_out.h rename to modules/core/include/vixen/hw/ata/cmds/proto_pio_data_out.h diff --git a/src/core/vixen/hw/ata/drvs/ata_device_driver.h b/modules/core/include/vixen/hw/ata/drvs/ata_device_driver.h similarity index 100% rename from src/core/vixen/hw/ata/drvs/ata_device_driver.h rename to modules/core/include/vixen/hw/ata/drvs/ata_device_driver.h diff --git a/src/core/vixen/hw/ata/drvs/drv_null.h b/modules/core/include/vixen/hw/ata/drvs/drv_null.h similarity index 100% rename from src/core/vixen/hw/ata/drvs/drv_null.h rename to modules/core/include/vixen/hw/ata/drvs/drv_null.h diff --git a/src/core/vixen/hw/ata/drvs/drv_vdvd_base.h b/modules/core/include/vixen/hw/ata/drvs/drv_vdvd_base.h similarity index 100% rename from src/core/vixen/hw/ata/drvs/drv_vdvd_base.h rename to modules/core/include/vixen/hw/ata/drvs/drv_vdvd_base.h diff --git a/src/core/vixen/hw/ata/drvs/drv_vdvd_dummy.h b/modules/core/include/vixen/hw/ata/drvs/drv_vdvd_dummy.h similarity index 100% rename from src/core/vixen/hw/ata/drvs/drv_vdvd_dummy.h rename to modules/core/include/vixen/hw/ata/drvs/drv_vdvd_dummy.h diff --git a/src/core/vixen/hw/ata/drvs/drv_vdvd_image.h b/modules/core/include/vixen/hw/ata/drvs/drv_vdvd_image.h similarity index 100% rename from src/core/vixen/hw/ata/drvs/drv_vdvd_image.h rename to modules/core/include/vixen/hw/ata/drvs/drv_vdvd_image.h diff --git a/src/core/vixen/hw/ata/drvs/drv_vhd_base.h b/modules/core/include/vixen/hw/ata/drvs/drv_vhd_base.h similarity index 100% rename from src/core/vixen/hw/ata/drvs/drv_vhd_base.h rename to modules/core/include/vixen/hw/ata/drvs/drv_vhd_base.h diff --git a/src/core/vixen/hw/ata/drvs/drv_vhd_dummy.h b/modules/core/include/vixen/hw/ata/drvs/drv_vhd_dummy.h similarity index 100% rename from src/core/vixen/hw/ata/drvs/drv_vhd_dummy.h rename to modules/core/include/vixen/hw/ata/drvs/drv_vhd_dummy.h diff --git a/src/core/vixen/hw/ata/drvs/drv_vhd_image.h b/modules/core/include/vixen/hw/ata/drvs/drv_vhd_image.h similarity index 100% rename from src/core/vixen/hw/ata/drvs/drv_vhd_image.h rename to modules/core/include/vixen/hw/ata/drvs/drv_vhd_image.h diff --git a/src/core/vixen/hw/ata/drvs/util.h b/modules/core/include/vixen/hw/ata/drvs/util.h similarity index 100% rename from src/core/vixen/hw/ata/drvs/util.h rename to modules/core/include/vixen/hw/ata/drvs/util.h diff --git a/src/core/vixen/hw/atapi/atapi_common.h b/modules/core/include/vixen/hw/atapi/atapi_common.h similarity index 100% rename from src/core/vixen/hw/atapi/atapi_common.h rename to modules/core/include/vixen/hw/atapi/atapi_common.h diff --git a/src/core/vixen/hw/atapi/atapi_defs.h b/modules/core/include/vixen/hw/atapi/atapi_defs.h similarity index 100% rename from src/core/vixen/hw/atapi/atapi_defs.h rename to modules/core/include/vixen/hw/atapi/atapi_defs.h diff --git a/src/core/vixen/hw/atapi/atapi_utils.h b/modules/core/include/vixen/hw/atapi/atapi_utils.h similarity index 100% rename from src/core/vixen/hw/atapi/atapi_utils.h rename to modules/core/include/vixen/hw/atapi/atapi_utils.h diff --git a/src/core/vixen/hw/atapi/atapi_xbox.h b/modules/core/include/vixen/hw/atapi/atapi_xbox.h similarity index 100% rename from src/core/vixen/hw/atapi/atapi_xbox.h rename to modules/core/include/vixen/hw/atapi/atapi_xbox.h diff --git a/src/core/vixen/hw/atapi/cmds/atapi_command.h b/modules/core/include/vixen/hw/atapi/cmds/atapi_command.h similarity index 100% rename from src/core/vixen/hw/atapi/cmds/atapi_command.h rename to modules/core/include/vixen/hw/atapi/cmds/atapi_command.h diff --git a/src/core/vixen/hw/atapi/cmds/cmd_mode_sense_10.h b/modules/core/include/vixen/hw/atapi/cmds/cmd_mode_sense_10.h similarity index 100% rename from src/core/vixen/hw/atapi/cmds/cmd_mode_sense_10.h rename to modules/core/include/vixen/hw/atapi/cmds/cmd_mode_sense_10.h diff --git a/src/core/vixen/hw/atapi/cmds/cmd_read_10.h b/modules/core/include/vixen/hw/atapi/cmds/cmd_read_10.h similarity index 100% rename from src/core/vixen/hw/atapi/cmds/cmd_read_10.h rename to modules/core/include/vixen/hw/atapi/cmds/cmd_read_10.h diff --git a/src/core/vixen/hw/atapi/cmds/cmd_read_capacity.h b/modules/core/include/vixen/hw/atapi/cmds/cmd_read_capacity.h similarity index 100% rename from src/core/vixen/hw/atapi/cmds/cmd_read_capacity.h rename to modules/core/include/vixen/hw/atapi/cmds/cmd_read_capacity.h diff --git a/src/core/vixen/hw/atapi/cmds/cmd_read_dvd_structure.h b/modules/core/include/vixen/hw/atapi/cmds/cmd_read_dvd_structure.h similarity index 100% rename from src/core/vixen/hw/atapi/cmds/cmd_read_dvd_structure.h rename to modules/core/include/vixen/hw/atapi/cmds/cmd_read_dvd_structure.h diff --git a/src/core/vixen/hw/atapi/cmds/cmd_test_unit_ready.h b/modules/core/include/vixen/hw/atapi/cmds/cmd_test_unit_ready.h similarity index 100% rename from src/core/vixen/hw/atapi/cmds/cmd_test_unit_ready.h rename to modules/core/include/vixen/hw/atapi/cmds/cmd_test_unit_ready.h diff --git a/src/core/vixen/hw/atapi/cmds/proto_data_in.h b/modules/core/include/vixen/hw/atapi/cmds/proto_data_in.h similarity index 100% rename from src/core/vixen/hw/atapi/cmds/proto_data_in.h rename to modules/core/include/vixen/hw/atapi/cmds/proto_data_in.h diff --git a/src/core/vixen/hw/atapi/cmds/proto_nondata.h b/modules/core/include/vixen/hw/atapi/cmds/proto_nondata.h similarity index 100% rename from src/core/vixen/hw/atapi/cmds/proto_nondata.h rename to modules/core/include/vixen/hw/atapi/cmds/proto_nondata.h diff --git a/src/core/vixen/hw/basic/char.h b/modules/core/include/vixen/hw/basic/char.h similarity index 98% rename from src/core/vixen/hw/basic/char.h rename to modules/core/include/vixen/hw/basic/char.h index b76726e..a4ca6dd 100644 --- a/src/core/vixen/hw/basic/char.h +++ b/modules/core/include/vixen/hw/basic/char.h @@ -2,7 +2,6 @@ #include -#include "vixen/cpu.h" #include "vixen/util/fifo.h" namespace vixen { diff --git a/src/core/vixen/hw/basic/char_null.h b/modules/core/include/vixen/hw/basic/char_null.h similarity index 100% rename from src/core/vixen/hw/basic/char_null.h rename to modules/core/include/vixen/hw/basic/char_null.h diff --git a/src/core/vixen/hw/basic/cmos.h b/modules/core/include/vixen/hw/basic/cmos.h similarity index 98% rename from src/core/vixen/hw/basic/cmos.h rename to modules/core/include/vixen/hw/basic/cmos.h index 7df0ef8..cc2dce5 100644 --- a/src/core/vixen/hw/basic/cmos.h +++ b/modules/core/include/vixen/hw/basic/cmos.h @@ -1,10 +1,10 @@ #pragma once +#include "vixen/io.h" + #include #include -#include "vixen/cpu.h" - namespace vixen { #define CMOS_IRQ 8 diff --git a/src/core/vixen/hw/basic/gsi.h b/modules/core/include/vixen/hw/basic/gsi.h similarity index 100% rename from src/core/vixen/hw/basic/gsi.h rename to modules/core/include/vixen/hw/basic/gsi.h diff --git a/src/core/vixen/hw/basic/i8254.h b/modules/core/include/vixen/hw/basic/i8254.h similarity index 100% rename from src/core/vixen/hw/basic/i8254.h rename to modules/core/include/vixen/hw/basic/i8254.h diff --git a/src/core/vixen/hw/basic/i8259.h b/modules/core/include/vixen/hw/basic/i8259.h similarity index 93% rename from src/core/vixen/hw/basic/i8259.h rename to modules/core/include/vixen/hw/basic/i8259.h index a876fea..0d5cd6a 100644 --- a/src/core/vixen/hw/basic/i8259.h +++ b/modules/core/include/vixen/hw/basic/i8259.h @@ -1,15 +1,14 @@ #pragma once #include - -#include "vixen/cpu.h" -#include "irq.h" - #include -namespace vixen { +#include "virt86/virt86.hpp" -using namespace vixen::cpu; +#include "vixen/io.h" +#include "irq.h" + +namespace vixen { #define PORT_PIC_MASTER_COMMAND 0x20 #define PORT_PIC_MASTER_DATA 0x21 @@ -28,7 +27,7 @@ using namespace vixen::cpu; class i8259 : public IODevice, public IRQHandler { public: - i8259(Cpu& cpu); + i8259(virt86::VirtualProcessor& cpu); virtual ~i8259(); void Reset(); @@ -41,7 +40,7 @@ public: int GetCurrentIRQ(); private: - Cpu& m_cpu; + virt86::VirtualProcessor& m_vp; uint8_t m_PreviousIRR[2]; // used for edge-detection uint8_t m_IRR[2]; diff --git a/src/core/vixen/hw/basic/interrupt.h b/modules/core/include/vixen/hw/basic/interrupt.h similarity index 100% rename from src/core/vixen/hw/basic/interrupt.h rename to modules/core/include/vixen/hw/basic/interrupt.h diff --git a/src/core/vixen/hw/basic/ioapic.h b/modules/core/include/vixen/hw/basic/ioapic.h similarity index 100% rename from src/core/vixen/hw/basic/ioapic.h rename to modules/core/include/vixen/hw/basic/ioapic.h diff --git a/src/core/vixen/hw/basic/irq.h b/modules/core/include/vixen/hw/basic/irq.h similarity index 100% rename from src/core/vixen/hw/basic/irq.h rename to modules/core/include/vixen/hw/basic/irq.h diff --git a/src/core/vixen/hw/basic/mcpx.h b/modules/core/include/vixen/hw/basic/mcpx.h similarity index 100% rename from src/core/vixen/hw/basic/mcpx.h rename to modules/core/include/vixen/hw/basic/mcpx.h diff --git a/src/core/vixen/hw/basic/serial.h b/modules/core/include/vixen/hw/basic/serial.h similarity index 99% rename from src/core/vixen/hw/basic/serial.h rename to modules/core/include/vixen/hw/basic/serial.h index 359559c..dc1890c 100644 --- a/src/core/vixen/hw/basic/serial.h +++ b/modules/core/include/vixen/hw/basic/serial.h @@ -2,7 +2,7 @@ #include -#include "vixen/cpu.h" +#include "vixen/io.h" #include "vixen/util/fifo.h" #include "vixen/util/invoke_later.h" #include "char.h" diff --git a/src/core/vixen/hw/basic/superio.h b/modules/core/include/vixen/hw/basic/superio.h similarity index 98% rename from src/core/vixen/hw/basic/superio.h rename to modules/core/include/vixen/hw/basic/superio.h index e2e892d..027e4ac 100644 --- a/src/core/vixen/hw/basic/superio.h +++ b/modules/core/include/vixen/hw/basic/superio.h @@ -2,7 +2,6 @@ #include -#include "vixen/cpu.h" #include "serial.h" namespace vixen { diff --git a/src/core/vixen/hw/bus/isabus.h b/modules/core/include/vixen/hw/bus/isabus.h similarity index 100% rename from src/core/vixen/hw/bus/isabus.h rename to modules/core/include/vixen/hw/bus/isabus.h diff --git a/src/core/vixen/hw/bus/pcibus.h b/modules/core/include/vixen/hw/bus/pcibus.h similarity index 100% rename from src/core/vixen/hw/bus/pcibus.h rename to modules/core/include/vixen/hw/bus/pcibus.h diff --git a/src/core/vixen/hw/bus/smbus.h b/modules/core/include/vixen/hw/bus/smbus.h similarity index 100% rename from src/core/vixen/hw/bus/smbus.h rename to modules/core/include/vixen/hw/bus/smbus.h diff --git a/src/core/vixen/hw/defs.h b/modules/core/include/vixen/hw/defs.h similarity index 100% rename from src/core/vixen/hw/defs.h rename to modules/core/include/vixen/hw/defs.h diff --git a/src/core/vixen/hw/nv2a/defs.h b/modules/core/include/vixen/hw/nv2a/defs.h similarity index 100% rename from src/core/vixen/hw/nv2a/defs.h rename to modules/core/include/vixen/hw/nv2a/defs.h diff --git a/src/core/vixen/hw/nv2a/nv2a_int.h b/modules/core/include/vixen/hw/nv2a/nv2a_int.h similarity index 100% rename from src/core/vixen/hw/nv2a/nv2a_int.h rename to modules/core/include/vixen/hw/nv2a/nv2a_int.h diff --git a/src/core/vixen/hw/nv2a/vga.h b/modules/core/include/vixen/hw/nv2a/vga.h similarity index 100% rename from src/core/vixen/hw/nv2a/vga.h rename to modules/core/include/vixen/hw/nv2a/vga.h diff --git a/src/core/vixen/hw/ohci/ohci.h b/modules/core/include/vixen/hw/ohci/ohci.h similarity index 98% rename from src/core/vixen/hw/ohci/ohci.h rename to modules/core/include/vixen/hw/ohci/ohci.h index 6ea9854..95fd5d2 100644 --- a/src/core/vixen/hw/ohci/ohci.h +++ b/modules/core/include/vixen/hw/ohci/ohci.h @@ -40,14 +40,13 @@ #pragma once +#include "virt86/virt86.hpp" + #include "../pci/usb_pci.h" #include "vixen/cxbxtimer.h" -#include "vixen/cpu.h" namespace vixen { -using namespace vixen::cpu; - // Abbreviations used: // OHCI: Open Host Controller Interface; the standard used on the Xbox to comunicate with the usb devices // HC: Host Controller; the hardware which interfaces with the usb device and the usb driver @@ -148,7 +147,7 @@ public: std::atomic_bool m_bFrameTime; // constructor - OHCI(Cpu& cpu, int Irqn, USBPCIDevice* UsbObj); + OHCI(virt86::VirtualProcessor& vp, int Irqn, USBPCIDevice* UsbObj); // destructor ~OHCI() {} // read a register @@ -157,7 +156,7 @@ public: void OHCI_WriteRegister(uint32_t Addr, uint32_t Value); private: - Cpu& m_cpu; + virt86::VirtualProcessor& m_vp; // pointer to g_USB0 or g_USB1 USBPCIDevice* m_UsbDevice = nullptr; // all the registers available in the OHCI standard diff --git a/src/core/vixen/hw/ohci/ohci_common.h b/modules/core/include/vixen/hw/ohci/ohci_common.h similarity index 100% rename from src/core/vixen/hw/ohci/ohci_common.h rename to modules/core/include/vixen/hw/ohci/ohci_common.h diff --git a/src/core/vixen/hw/ohci/ohci_hub.h b/modules/core/include/vixen/hw/ohci/ohci_hub.h similarity index 100% rename from src/core/vixen/hw/ohci/ohci_hub.h rename to modules/core/include/vixen/hw/ohci/ohci_hub.h diff --git a/src/core/vixen/hw/pci/ac97.h b/modules/core/include/vixen/hw/pci/ac97.h similarity index 100% rename from src/core/vixen/hw/pci/ac97.h rename to modules/core/include/vixen/hw/pci/ac97.h diff --git a/src/core/vixen/hw/pci/agpbridge.h b/modules/core/include/vixen/hw/pci/agpbridge.h similarity index 100% rename from src/core/vixen/hw/pci/agpbridge.h rename to modules/core/include/vixen/hw/pci/agpbridge.h diff --git a/src/core/vixen/hw/pci/bmide.h b/modules/core/include/vixen/hw/pci/bmide.h similarity index 97% rename from src/core/vixen/hw/pci/bmide.h rename to modules/core/include/vixen/hw/pci/bmide.h index 4381621..f0b93ea 100644 --- a/src/core/vixen/hw/pci/bmide.h +++ b/modules/core/include/vixen/hw/pci/bmide.h @@ -12,7 +12,7 @@ #include "../defs.h" #include "pci.h" -#include "bmide/bmide_defs.h" +#include "bmide_defs.h" #include "bmide_channel.h" #include "vixen/hw/ata/ata.h" diff --git a/src/core/vixen/hw/pci/bmide_channel.h b/modules/core/include/vixen/hw/pci/bmide_channel.h similarity index 98% rename from src/core/vixen/hw/pci/bmide_channel.h rename to modules/core/include/vixen/hw/pci/bmide_channel.h index 3dd400e..c07eca8 100644 --- a/src/core/vixen/hw/pci/bmide_channel.h +++ b/modules/core/include/vixen/hw/pci/bmide_channel.h @@ -10,7 +10,7 @@ #include #include -#include "bmide/bmide_defs.h" +#include "vixen/hw/pci/bmide_defs.h" #include "vixen/hw/ata/ata_common.h" #include "vixen/hw/ata/ata.h" diff --git a/src/core/vixen/hw/pci/bmide/bmide_defs.h b/modules/core/include/vixen/hw/pci/bmide_defs.h similarity index 100% rename from src/core/vixen/hw/pci/bmide/bmide_defs.h rename to modules/core/include/vixen/hw/pci/bmide_defs.h diff --git a/src/core/vixen/hw/pci/hostbridge.h b/modules/core/include/vixen/hw/pci/hostbridge.h similarity index 100% rename from src/core/vixen/hw/pci/hostbridge.h rename to modules/core/include/vixen/hw/pci/hostbridge.h diff --git a/src/core/vixen/hw/pci/lpc.h b/modules/core/include/vixen/hw/pci/lpc.h similarity index 100% rename from src/core/vixen/hw/pci/lpc.h rename to modules/core/include/vixen/hw/pci/lpc.h diff --git a/src/core/vixen/hw/pci/mcpx_ram.h b/modules/core/include/vixen/hw/pci/mcpx_ram.h similarity index 100% rename from src/core/vixen/hw/pci/mcpx_ram.h rename to modules/core/include/vixen/hw/pci/mcpx_ram.h diff --git a/src/core/vixen/hw/pci/nv2a.h b/modules/core/include/vixen/hw/pci/nv2a.h similarity index 100% rename from src/core/vixen/hw/pci/nv2a.h rename to modules/core/include/vixen/hw/pci/nv2a.h diff --git a/src/core/vixen/hw/pci/nvapu.h b/modules/core/include/vixen/hw/pci/nvapu.h similarity index 100% rename from src/core/vixen/hw/pci/nvapu.h rename to modules/core/include/vixen/hw/pci/nvapu.h diff --git a/src/core/vixen/hw/pci/nvnet.h b/modules/core/include/vixen/hw/pci/nvnet.h similarity index 100% rename from src/core/vixen/hw/pci/nvnet.h rename to modules/core/include/vixen/hw/pci/nvnet.h diff --git a/src/core/vixen/hw/pci/pci.h b/modules/core/include/vixen/hw/pci/pci.h similarity index 100% rename from src/core/vixen/hw/pci/pci.h rename to modules/core/include/vixen/hw/pci/pci.h diff --git a/src/core/vixen/hw/pci/pci_common.h b/modules/core/include/vixen/hw/pci/pci_common.h similarity index 100% rename from src/core/vixen/hw/pci/pci_common.h rename to modules/core/include/vixen/hw/pci/pci_common.h diff --git a/src/core/vixen/hw/pci/pci_irq.h b/modules/core/include/vixen/hw/pci/pci_irq.h similarity index 100% rename from src/core/vixen/hw/pci/pci_irq.h rename to modules/core/include/vixen/hw/pci/pci_irq.h diff --git a/src/core/vixen/hw/pci/pci_regs.h b/modules/core/include/vixen/hw/pci/pci_regs.h similarity index 100% rename from src/core/vixen/hw/pci/pci_regs.h rename to modules/core/include/vixen/hw/pci/pci_regs.h diff --git a/src/core/vixen/hw/pci/pcibridge.h b/modules/core/include/vixen/hw/pci/pcibridge.h similarity index 100% rename from src/core/vixen/hw/pci/pcibridge.h rename to modules/core/include/vixen/hw/pci/pcibridge.h diff --git a/src/core/vixen/hw/pci/usb_pci.h b/modules/core/include/vixen/hw/pci/usb_pci.h similarity index 98% rename from src/core/vixen/hw/pci/usb_pci.h rename to modules/core/include/vixen/hw/pci/usb_pci.h index 88d077f..a9e78f6 100644 --- a/src/core/vixen/hw/pci/usb_pci.h +++ b/modules/core/include/vixen/hw/pci/usb_pci.h @@ -42,15 +42,14 @@ #include +#include "virt86/virt86.hpp" + #include "../defs.h" #include "pci.h" #include "../ohci/ohci_common.h" -#include "vixen/cpu.h" namespace vixen { -using namespace vixen::cpu; - typedef enum USBDeviceFlags { USB_DEV_FLAG_FULL_PATH, USB_DEV_FLAG_IS_HOST, @@ -66,7 +65,7 @@ class OHCI; class USBPCIDevice : public PCIDevice { public: // constructor - USBPCIDevice(uint8_t irqn, Cpu& cpu); + USBPCIDevice(uint8_t irqn, virt86::VirtualProcessor& vp); virtual ~USBPCIDevice(); // PCI Device functions @@ -207,7 +206,7 @@ public: const char* USBDesc_GetString(XboxDeviceState* dev, int index); private: uint8_t m_irqn; - Cpu& m_cpu; + virt86::VirtualProcessor& m_vp; }; } diff --git a/src/core/vixen/hw/sm/adm1032.h b/modules/core/include/vixen/hw/sm/adm1032.h similarity index 100% rename from src/core/vixen/hw/sm/adm1032.h rename to modules/core/include/vixen/hw/sm/adm1032.h diff --git a/src/core/vixen/hw/sm/eeprom.h b/modules/core/include/vixen/hw/sm/eeprom.h similarity index 100% rename from src/core/vixen/hw/sm/eeprom.h rename to modules/core/include/vixen/hw/sm/eeprom.h diff --git a/src/core/vixen/hw/sm/led.h b/modules/core/include/vixen/hw/sm/led.h similarity index 100% rename from src/core/vixen/hw/sm/led.h rename to modules/core/include/vixen/hw/sm/led.h diff --git a/src/core/vixen/hw/sm/sm.h b/modules/core/include/vixen/hw/sm/sm.h similarity index 100% rename from src/core/vixen/hw/sm/sm.h rename to modules/core/include/vixen/hw/sm/sm.h diff --git a/src/core/vixen/hw/sm/smc.h b/modules/core/include/vixen/hw/sm/smc.h similarity index 100% rename from src/core/vixen/hw/sm/smc.h rename to modules/core/include/vixen/hw/sm/smc.h diff --git a/src/core/vixen/hw/sm/tvenc.h b/modules/core/include/vixen/hw/sm/tvenc.h similarity index 100% rename from src/core/vixen/hw/sm/tvenc.h rename to modules/core/include/vixen/hw/sm/tvenc.h diff --git a/src/core/vixen/hw/sm/tvenc_conexant.h b/modules/core/include/vixen/hw/sm/tvenc_conexant.h similarity index 100% rename from src/core/vixen/hw/sm/tvenc_conexant.h rename to modules/core/include/vixen/hw/sm/tvenc_conexant.h diff --git a/src/core/vixen/hw/utils.h b/modules/core/include/vixen/hw/utils.h similarity index 100% rename from src/core/vixen/hw/utils.h rename to modules/core/include/vixen/hw/utils.h diff --git a/src/core/vixen/hw/xid/xid_gamepad.h b/modules/core/include/vixen/hw/xid/xid_gamepad.h similarity index 100% rename from src/core/vixen/hw/xid/xid_gamepad.h rename to modules/core/include/vixen/hw/xid/xid_gamepad.h diff --git a/src/common/vixen/io.h b/modules/core/include/vixen/io.h similarity index 100% rename from src/common/vixen/io.h rename to modules/core/include/vixen/io.h diff --git a/src/common/vixen/iovec.h b/modules/core/include/vixen/iovec.h similarity index 100% rename from src/common/vixen/iovec.h rename to modules/core/include/vixen/iovec.h diff --git a/src/common/vixen/log.h b/modules/core/include/vixen/log.h similarity index 100% rename from src/common/vixen/log.h rename to modules/core/include/vixen/log.h diff --git a/src/core/vixen/mem.h b/modules/core/include/vixen/mem.h similarity index 84% rename from src/core/vixen/mem.h rename to modules/core/include/vixen/mem.h index 7fa7d13..48226e1 100644 --- a/src/core/vixen/mem.h +++ b/modules/core/include/vixen/mem.h @@ -17,8 +17,8 @@ namespace vixen { // The kernel image is decrypted and extracted at physical address 0x10000 and // manually mapped to virtual address 0x80010000. -#define XBOX_RAM_SIZE_RETAIL MiB(64) -#define XBOX_RAM_SIZE_DEBUG MiB(128) -#define XBOX_ROM_AREA_SIZE MiB(16) +#define XBOX_RAM_SIZE_RETAIL (64 * MiB) +#define XBOX_RAM_SIZE_DEBUG (128 * MiB) +#define XBOX_ROM_AREA_SIZE (16 * MiB) } diff --git a/src/common/vixen/queue.h b/modules/core/include/vixen/queue.h similarity index 100% rename from src/common/vixen/queue.h rename to modules/core/include/vixen/queue.h diff --git a/src/core/vixen/settings.h b/modules/core/include/vixen/settings.h similarity index 100% rename from src/core/vixen/settings.h rename to modules/core/include/vixen/settings.h diff --git a/modules/core/include/vixen/status.h b/modules/core/include/vixen/status.h new file mode 100644 index 0000000..6d253b0 --- /dev/null +++ b/modules/core/include/vixen/status.h @@ -0,0 +1,30 @@ +#pragma once + +namespace vixen { + +enum EmulatorStatus { + EMUS_OK = 0, // Operation completed successfully + + EMUS_INIT_INVALID_REVISION, // An invalid hardware revision was specified + + EMUS_INIT_VM_INIT_FAILED, // Could not initialize virtual machine + + EMUS_INIT_ALLOC_RAM_FAILED, // Could not allocate memory for the guest RAM + EMUS_INIT_ALLOC_RAM_RGN_FAILED, // Could not allocate memory for the RAM region + + EMUS_INIT_ALLOC_ROM_FAILED, // Could not allocate memory for the guest ROM + EMUS_INIT_ALLOC_ROM_RGN_FAILED, // Could not allocate memory for the ROM region + EMUS_INIT_MCPX_ROM_NOT_FOUND, // MCPX ROM file not found + EMUS_INIT_MCPX_ROM_INVALID_SIZE, // MCPX ROM provided has incorrect size (must be 512 bytes) + EMUS_INIT_BIOS_ROM_NOT_FOUND, // BIOS ROM file not found + EMUS_INIT_BIOS_ROM_INVALID_SIZE, // BIOS ROM provided has incorrect size (must be 256 KiB or 1 MiB) + + EMUS_INIT_INVALID_HARD_DRIVE_TYPE, // An invalid hard drive type was specified + EMUS_INIT_HARD_DRIVE_INIT_FAILED, // Virtual hard drive initialization failed + EMUS_INIT_INVALID_DVD_DRIVE_TYPE, // An invalid DVD drive type was specified + EMUS_INIT_DVD_DRIVE_INIT_FAILED, // Virtual DVD drive initialization failed + + EMUS_INIT_DEBUGGER_FAILED, // Debugger initialization failed +}; + +} diff --git a/src/common/vixen/thread.h b/modules/core/include/vixen/thread.h similarity index 100% rename from src/common/vixen/thread.h rename to modules/core/include/vixen/thread.h diff --git a/src/core/vixen/timer.h b/modules/core/include/vixen/timer.h similarity index 100% rename from src/core/vixen/timer.h rename to modules/core/include/vixen/timer.h diff --git a/src/core/vixen/util.h b/modules/core/include/vixen/util.h similarity index 95% rename from src/core/vixen/util.h rename to modules/core/include/vixen/util.h index 3dfd678..897168d 100644 --- a/src/core/vixen/util.h +++ b/modules/core/include/vixen/util.h @@ -6,9 +6,6 @@ namespace vixen { -#define KiB(x) (x * 1024) -#define MiB(x) (x * KiB(1024)) - #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) #define ALIGN_DOWN_SIZE(length, size) \ diff --git a/src/core/vixen/util/fifo.h b/modules/core/include/vixen/util/fifo.h similarity index 100% rename from src/core/vixen/util/fifo.h rename to modules/core/include/vixen/util/fifo.h diff --git a/src/core/vixen/util/invoke_later.h b/modules/core/include/vixen/util/invoke_later.h similarity index 100% rename from src/core/vixen/util/invoke_later.h rename to modules/core/include/vixen/util/invoke_later.h diff --git a/src/core/vixen/xbox.h b/modules/core/include/vixen/xbox.h similarity index 83% rename from src/core/vixen/xbox.h rename to modules/core/include/vixen/xbox.h index 54427e6..ca4fd30 100644 --- a/src/core/vixen/xbox.h +++ b/modules/core/include/vixen/xbox.h @@ -10,9 +10,8 @@ #include #include -#include "vixen/cpu.h" -#include "vixen/dev.h" -#include "vixen/emulator.h" +#include "virt86/virt86.hpp" + #include "vixen/gdbserver.h" #include "vixen/log.h" #include "vixen/mem.h" @@ -50,8 +49,6 @@ #include "vixen/hw/pci/bmide.h" #include "vixen/hw/pci/nv2a.h" -#include "vixen/cpu_module.h" - namespace vixen { /*! @@ -70,9 +67,9 @@ struct XboxKernelVersion { * This class is the top-level class, will perform initialization and high-level * management of the overall emulation flow. */ -class Xbox : Emulator { +class Xbox { public: - Xbox(vixen::modules::cpu::ICPUModule *cpuModule); + Xbox(virt86::Platform& platform); virtual ~Xbox(); viXenSettings& GetSettings() { return m_settings; } @@ -85,33 +82,40 @@ protected: // ----- Initialization and cleanup --------------------------------------- EmulatorStatus Initialize(); EmulatorStatus InitFixupSettings(); + EmulatorStatus InitVM(); EmulatorStatus InitMemory(); EmulatorStatus InitRAM(); EmulatorStatus InitROM(); - EmulatorStatus InitCPU(); EmulatorStatus InitHardware(); EmulatorStatus InitDebugger(); void Cleanup(); // ----- Thread functions ------------------------------------------------- + static uint32_t EmuCpuThreadFunc(void *data); int RunCpu(); - // ----- Friends ---------------------------------------------------------- - static uint32_t EmuCpuThreadFunc(void *data); + // ----- I/O callbacks ---------------------------------------------------- + static uint32_t IOReadCallback(void *context, uint16_t port, size_t size); + static void IOWriteCallback(void *context, uint16_t port, size_t size, uint32_t value); + static uint64_t MMIOReadCallback(void *context, uint64_t address, size_t size); + static void MMIOWriteCallback(void *context, uint64_t address, size_t size, uint64_t value); - // ----- Modules ---------------------------------------------------------- - vixen::modules::cpu::ICPUModule *m_cpuModule; + uint32_t IORead(uint16_t port, size_t size); + void IOWrite(uint16_t port, size_t size, uint32_t value); + uint64_t MMIORead(uint64_t address, size_t size); + void MMIOWrite(uint64_t address, size_t size, uint64_t value); // ----- Hardware --------------------------------------------------------- - Cpu *m_cpu = nullptr; + virt86::Platform& m_virt86Platform; + std::optional> m_vm; + uint32_t m_ramSize = 0; uint8_t *m_ram = nullptr; uint8_t *m_rom = nullptr; uint8_t *m_bios = nullptr; uint32_t m_biosSize = 0; uint8_t *m_mcpxROM = nullptr; - MemoryRegion *m_memRegion = nullptr; IOMapper m_ioMapper; GSI *m_GSI = nullptr; diff --git a/src/core/vixen/pch.cpp b/modules/core/src/common/pch.cpp similarity index 84% rename from src/core/vixen/pch.cpp rename to modules/core/src/common/pch.cpp index 6f30752..485ebaf 100644 --- a/src/core/vixen/pch.cpp +++ b/modules/core/src/common/pch.cpp @@ -1,4 +1,4 @@ -#include "vixen/pch.h" +#include "pch.hpp" // This file exists for the sole purpose of telling CMake that there is a // precompiled header file to be... well, precompiled. diff --git a/src/core/vixen/pch.h b/modules/core/src/common/pch.hpp similarity index 85% rename from src/core/vixen/pch.h rename to modules/core/src/common/pch.hpp index cf6fdef..5229821 100644 --- a/src/core/vixen/pch.h +++ b/modules/core/src/common/pch.hpp @@ -2,9 +2,9 @@ // This is the precompiled header file for this project. -#include "vixen/platform.h" +#include "virt86/virt86.hpp" + #include "vixen/settings.h" -#include "vixen/pte.h" #include "vixen/log.h" #include "vixen/util.h" diff --git a/src/core/vixen/core.cpp b/modules/core/src/common/vixen/core.cpp similarity index 100% rename from src/core/vixen/core.cpp rename to modules/core/src/common/vixen/core.cpp diff --git a/src/common/vixen/cxbxtimer.cpp b/modules/core/src/common/vixen/cxbxtimer.cpp similarity index 99% rename from src/common/vixen/cxbxtimer.cpp rename to modules/core/src/common/vixen/cxbxtimer.cpp index 4ec499b..18d2521 100644 --- a/src/common/vixen/cxbxtimer.cpp +++ b/modules/core/src/common/vixen/cxbxtimer.cpp @@ -37,7 +37,7 @@ #include #include #include -#include "cxbxtimer.h" +#include "vixen/cxbxtimer.h" namespace vixen { diff --git a/modules/core/src/common/vixen/debug.cpp b/modules/core/src/common/vixen/debug.cpp new file mode 100644 index 0000000..3d06d23 --- /dev/null +++ b/modules/core/src/common/vixen/debug.cpp @@ -0,0 +1,292 @@ +#include "vixen/debug.h" +//#include + +#include "virt86/virt86.hpp" + +#include +#include + +namespace vixen { + +using namespace virt86; + + +#define PRINT_FLAG(flags, prefix, flag) \ +do { \ + if (flags & prefix##_##flag) log_debug(" " #flag); \ +} while (0) + +void printRFLAGSBits(uint64_t rflags) { + PRINT_FLAG(rflags, RFLAGS, CF); + PRINT_FLAG(rflags, RFLAGS, PF); + PRINT_FLAG(rflags, RFLAGS, AF); + PRINT_FLAG(rflags, RFLAGS, ZF); + PRINT_FLAG(rflags, RFLAGS, SF); + PRINT_FLAG(rflags, RFLAGS, TF); + PRINT_FLAG(rflags, RFLAGS, IF); + PRINT_FLAG(rflags, RFLAGS, DF); + PRINT_FLAG(rflags, RFLAGS, OF); + PRINT_FLAG(rflags, RFLAGS, NT); + PRINT_FLAG(rflags, RFLAGS, RF); + PRINT_FLAG(rflags, RFLAGS, VM); + PRINT_FLAG(rflags, RFLAGS, AC); + PRINT_FLAG(rflags, RFLAGS, VIF); + PRINT_FLAG(rflags, RFLAGS, VIP); + PRINT_FLAG(rflags, RFLAGS, ID); + uint8_t iopl = (rflags & RFLAGS_IOPL) >> RFLAGS_IOPL_SHIFT; + log_debug(" IOPL=%u", iopl); +} + +void printEFERBits(uint64_t efer) { + PRINT_FLAG(efer, EFER, SCE); + PRINT_FLAG(efer, EFER, LME); + PRINT_FLAG(efer, EFER, LMA); + PRINT_FLAG(efer, EFER, NXE); + PRINT_FLAG(efer, EFER, SVME); + PRINT_FLAG(efer, EFER, LMSLE); + PRINT_FLAG(efer, EFER, FFXSR); + PRINT_FLAG(efer, EFER, TCE); +} + +void printCR0Bits(uint64_t cr0) { + PRINT_FLAG(cr0, CR0, PE); + PRINT_FLAG(cr0, CR0, MP); + PRINT_FLAG(cr0, CR0, EM); + PRINT_FLAG(cr0, CR0, TS); + PRINT_FLAG(cr0, CR0, ET); + PRINT_FLAG(cr0, CR0, NE); + PRINT_FLAG(cr0, CR0, WP); + PRINT_FLAG(cr0, CR0, AM); + PRINT_FLAG(cr0, CR0, NW); + PRINT_FLAG(cr0, CR0, CD); + PRINT_FLAG(cr0, CR0, PG); +} + +void printCR4Bits(uint64_t cr4) { + PRINT_FLAG(cr4, CR4, VME); + PRINT_FLAG(cr4, CR4, PVI); + PRINT_FLAG(cr4, CR4, TSD); + PRINT_FLAG(cr4, CR4, DE); + PRINT_FLAG(cr4, CR4, PSE); + PRINT_FLAG(cr4, CR4, PAE); + PRINT_FLAG(cr4, CR4, MCE); + PRINT_FLAG(cr4, CR4, PGE); + PRINT_FLAG(cr4, CR4, PCE); + PRINT_FLAG(cr4, CR4, OSFXSR); + PRINT_FLAG(cr4, CR4, OSXMMEXCPT); + PRINT_FLAG(cr4, CR4, UMIP); + PRINT_FLAG(cr4, CR4, VMXE); + PRINT_FLAG(cr4, CR4, SMXE); + PRINT_FLAG(cr4, CR4, PCID); + PRINT_FLAG(cr4, CR4, OSXSAVE); + PRINT_FLAG(cr4, CR4, SMEP); + PRINT_FLAG(cr4, CR4, SMAP); +} + +void printCR8Bits(uint64_t cr8) { + uint8_t tpr = cr8 & CR8_TPR; + log_debug(" TPR=%d", tpr); +} + +void printXCR0Bits(uint64_t xcr0) { + PRINT_FLAG(xcr0, XCR0, FP); + PRINT_FLAG(xcr0, XCR0, SSE); + PRINT_FLAG(xcr0, XCR0, AVX); + PRINT_FLAG(xcr0, XCR0, BNDREG); + PRINT_FLAG(xcr0, XCR0, BNDCSR); + PRINT_FLAG(xcr0, XCR0, opmask); + PRINT_FLAG(xcr0, XCR0, ZMM_Hi256); + PRINT_FLAG(xcr0, XCR0, Hi16_ZMM); + PRINT_FLAG(xcr0, XCR0, PKRU); +} + +void printDR6Bits(uint64_t dr6) { + PRINT_FLAG(dr6, DR6, BP0); + PRINT_FLAG(dr6, DR6, BP1); + PRINT_FLAG(dr6, DR6, BP2); + PRINT_FLAG(dr6, DR6, BP3); +} + +void printDR7Bits(uint64_t dr7) { + for (uint8_t i = 0; i < 4; i++) { + if (dr7 & (DR7_LOCAL(i) | DR7_GLOBAL(i))) { + log_debug(" BP%u[", i); + + if (dr7 & DR7_LOCAL(i)) log_debug("L"); + if (dr7 & DR7_GLOBAL(i)) log_debug("G"); + + uint8_t size = (dr7 & DR7_SIZE(i)) >> DR7_SIZE_SHIFT(i); + switch (size) { + case DR7_SIZE_BYTE: log_debug(" byte"); break; + case DR7_SIZE_WORD: log_debug(" word"); break; + case DR7_SIZE_QWORD: log_debug(" qword"); break; + case DR7_SIZE_DWORD: log_debug(" dword"); break; + } + + uint8_t cond = (dr7 & DR7_COND(i)) >> DR7_COND_SHIFT(i); + switch (cond) { + case DR7_COND_EXEC: log_debug(" exec"); break; + case DR7_COND_WIDTH8: log_debug(" width8"); break; + case DR7_COND_WRITE: log_debug(" write"); break; + case DR7_COND_READWRITE: log_debug(" r/w"); break; + } + + log_debug("]"); + } + } +} +#undef PRINT_FLAG + + +void DumpCPURegisters(VirtualProcessor& vp) { +#define READREG(code, name) RegValue name; vp.RegRead(code, name); + READREG(Reg::RAX, rax); READREG(Reg::RCX, rcx); READREG(Reg::RDX, rdx); READREG(Reg::RBX, rbx); + READREG(Reg::RSP, rsp); READREG(Reg::RBP, rbp); READREG(Reg::RSI, rsi); READREG(Reg::RDI, rdi); + READREG(Reg::R8, r8); READREG(Reg::R9, r9); READREG(Reg::R10, r10); READREG(Reg::R11, r11); + READREG(Reg::R12, r12); READREG(Reg::R13, r13); READREG(Reg::R14, r14); READREG(Reg::R15, r15); + READREG(Reg::RIP, rip); + READREG(Reg::CS, cs); READREG(Reg::SS, ss); + READREG(Reg::DS, ds); READREG(Reg::ES, es); + READREG(Reg::FS, fs); READREG(Reg::GS, gs); + READREG(Reg::LDTR, ldtr); READREG(Reg::TR, tr); + READREG(Reg::GDTR, gdtr); + READREG(Reg::IDTR, idtr); + READREG(Reg::RFLAGS, rflags); + READREG(Reg::EFER, efer); + READREG(Reg::CR2, cr2); READREG(Reg::CR0, cr0); + READREG(Reg::CR3, cr3); READREG(Reg::CR4, cr4); + READREG(Reg::DR0, dr0); READREG(Reg::CR8, cr8); + READREG(Reg::DR1, dr1); READREG(Reg::XCR0, xcr0); + READREG(Reg::DR2, dr2); READREG(Reg::DR6, dr6); + READREG(Reg::DR3, dr3); READREG(Reg::DR7, dr7); +#undef READREG + + auto extendedRegs = BitmaskEnum(vp.GetVirtualMachine().GetPlatform().GetFeatures().extendedControlRegisters); + + log_debug(" RAX = %016" PRIx64 " RCX = %016" PRIx64 " RDX = %016" PRIx64 " RBX = %016" PRIx64 "\n", rax.u64, rcx.u64, rdx.u64, rbx.u64); + log_debug(" RSP = %016" PRIx64 " RBP = %016" PRIx64 " RSI = %016" PRIx64 " RDI = %016" PRIx64 "\n", rsp.u64, rbp.u64, rsi.u64, rdi.u64); + log_debug(" R8 = %016" PRIx64 " R9 = %016" PRIx64 " R10 = %016" PRIx64 " R11 = %016" PRIx64 "\n", r8.u64, r9.u64, r10.u64, r11.u64); + log_debug(" R12 = %016" PRIx64 " R13 = %016" PRIx64 " R14 = %016" PRIx64 " R15 = %016" PRIx64 "\n", r12.u64, r13.u64, r14.u64, r15.u64); + log_debug(" RIP = %016" PRIx64 "\n", rip.u64); + log_debug(" CS = %04x -> %016" PRIx64 ":%08x [%04x] SS = %04x -> %016" PRIx64 ":%08x [%04x]\n", cs.segment.selector, cs.segment.base, cs.segment.limit, cs.segment.attributes.u16, ss.segment.selector, ss.segment.base, ss.segment.limit, ss.segment.attributes.u16); + log_debug(" DS = %04x -> %016" PRIx64 ":%08x [%04x] ES = %04x -> %016" PRIx64 ":%08x [%04x]\n", ds.segment.selector, ds.segment.base, ds.segment.limit, ds.segment.attributes.u16, es.segment.selector, es.segment.base, es.segment.limit, es.segment.attributes.u16); + log_debug(" FS = %04x -> %016" PRIx64 ":%08x [%04x] GS = %04x -> %016" PRIx64 ":%08x [%04x]\n", fs.segment.selector, fs.segment.base, fs.segment.limit, fs.segment.attributes.u16, gs.segment.selector, gs.segment.base, gs.segment.limit, gs.segment.attributes.u16); + log_debug("LDTR = %04x -> %016" PRIx64 ":%08x [%04x] TR = %04x -> %016" PRIx64 ":%08x [%04x]\n", ldtr.segment.selector, ldtr.segment.base, ldtr.segment.limit, ldtr.segment.attributes.u16, tr.segment.selector, tr.segment.base, tr.segment.limit, tr.segment.attributes.u16); + log_debug("GDTR = %016" PRIx64 ":%04x\n", gdtr.table.base, gdtr.table.limit); + log_debug("IDTR = %016" PRIx64 ":%04x\n", idtr.table.base, idtr.table.limit); + log_debug("RFLAGS = %016" PRIx64 "", rflags.u64); printRFLAGSBits(rflags.u64); log_debug("\n"); + log_debug("EFER = %016" PRIx64, efer.u64); printEFERBits(efer.u64); log_debug("\n"); + + log_debug(" CR2 = %016" PRIx64 " CR0 = %016" PRIx64 "", cr2.u64, cr0.u64); printCR0Bits(cr0.u64); log_debug("\n"); + log_debug(" CR3 = %016" PRIx64 " CR4 = %016" PRIx64 "", cr3.u64, cr4.u64); printCR4Bits(cr4.u64); log_debug("\n"); + log_debug(" DR0 = %016" PRIx64 " CR8 = ", dr0.u64); + if (extendedRegs.AnyOf(ExtendedControlRegister::CR8)) { + log_debug("%016" PRIx64 "", cr8.u64); printCR8Bits(cr8.u64); log_debug("\n"); + } + else { + log_debug("................\n"); + } + log_debug(" DR1 = %016" PRIx64 " XCR0 = ", dr1.u64); + if (extendedRegs.AnyOf(ExtendedControlRegister::XCR0)) { + log_debug("%016" PRIx64 "", xcr0.u64); printXCR0Bits(xcr0.u64); log_debug("\n"); + } + else { + log_debug("................\n"); + } + log_debug(" DR2 = %016" PRIx64 " DR6 = %016" PRIx64 "", dr2.u64, dr6.u64); printDR6Bits(dr6.u64); log_debug("\n"); + log_debug(" DR3 = %016" PRIx64 " DR7 = %016" PRIx64 "", dr3.u64, dr7.u64); printDR7Bits(dr7.u64); log_debug("\n"); +} + +void DumpCPUStack(VirtualProcessor& vp, int32_t offsetStart, int32_t offsetEnd) { + RegValue esp, ebp; + vp.RegRead(Reg::ESP, esp); + vp.RegRead(Reg::EBP, ebp); + log_debug("Stack:\n"); + for (int i = offsetStart; i <= offsetEnd; i += 0x4) { + uint32_t val; + if (vp.LMemRead(esp.u32 + i, 4, &val)) { + log_debug("%s %08x [esp%c%02x] = %08x%s\n", ((i == 0) ? "=>" : " "), esp.u32 + i, ((i < 0) ? '-' : '+'), ((i < 0) ? -i : i), val, ((esp.u32 + i) == ebp.u32) ? " <= EBP" : ""); + } + else { + log_debug("%s %08x [esp%c%02x] = ........%s\n", ((i == 0) ? "=>" : " "), esp.u32 + i, ((i < 0) ? '-' : '+'), ((i < 0) ? -i : i), ((esp.u32 + i) == ebp.u32) ? " <= EBP" : ""); + } + } + log_debug("\n"); +} + +void DumpCPUMemory(VirtualProcessor& vp, uint32_t address, uint32_t size, bool physical) { + log_debug("%s memory at 0x%08x:\n", (physical ? "Physical" : "Linear"), address); + char *mem = new char[size]; + if (physical) { + if (vp.MemRead(address, size, mem)) { + log_debug("\n\n"); + delete[] mem; + return; + } + } + else { + if (vp.LMemRead(address, size, mem)) { + log_debug("\n\n"); + delete[] mem; + return; + } + } + + for (uint32_t i = 0x00; i < size; i++) { + if ((i & 0xF) == 0x0) { + log_debug("%08x ", address + i); + } + if ((i & 0xF) == 0x8) { + log_debug(" "); + } + log_debug("%02x ", mem[i] & 0xFF); + if ((i & 0xF) == 0xF) { + log_debug("\n"); + } + } + if (size & 0xF) { log_debug("\n"); } + log_debug("\n"); + + delete[] mem; +} + +void DumpCPUDisassembly(VirtualProcessor& vp, uint32_t address, uint32_t count, bool physical) { + // TODO: fix CMakeLists.txt to include Zydis + /*log_debug("%s memory disassembly at 0x%08x:\n", (physical ? "Physical" : "Virtual"), address); + uint8_t mem[16]; + + ZydisDecoder decoder; + ZydisDecoderInit(&decoder, + ZYDIS_MACHINE_MODE_LEGACY_32, + ZYDIS_ADDRESS_WIDTH_32); + + ZydisFormatter formatter; + ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL); + + ZydisDecodedInstruction instruction; + + for (uint32_t i = 0; i < count; i++) { + if (physical) { + if (cpu->MemRead(address, 16, mem)) { + log_debug("\n\n"); + return; + } + } + else { + if (cpu->VMemRead(address, 16, mem)) { + log_debug("\n\n"); + return; + } + } + + auto result = ZydisDecoderDecodeBuffer(&decoder, mem, 16, address, &instruction); + if (ZYDIS_SUCCESS(result)) { + char buffer[256]; + ZydisFormatterFormatInstruction(&formatter, &instruction, buffer, sizeof(buffer)); + log_debug("%08x %s\n", address, buffer); + } + address += instruction.length; + }*/ +} + +} diff --git a/src/core/vixen/gdbserver.cpp b/modules/core/src/common/vixen/gdbserver.cpp similarity index 93% rename from src/core/vixen/gdbserver.cpp rename to modules/core/src/common/vixen/gdbserver.cpp index 97197f1..7239ef4 100644 --- a/src/core/vixen/gdbserver.cpp +++ b/modules/core/src/common/vixen/gdbserver.cpp @@ -16,11 +16,11 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "gdbserver.h" +#include "vixen/gdbserver.h" namespace vixen { -using namespace vixen::cpu; +using namespace virt86; #ifdef _WIN32 int inet_aton(const char *cp, struct in_addr *inp) { return InetPton(AF_INET, cp, inp); } @@ -75,8 +75,8 @@ using namespace vixen::cpu; /*! * Constructor */ -GdbServer::GdbServer(Cpu *cpu, const char *bind_host, int bind_port) -: m_cpu(cpu), m_bind_host(bind_host), m_bind_port(bind_port) +GdbServer::GdbServer(VirtualProcessor& vp, const char *bind_host, int bind_port) +: m_vp(vp), m_bind_host(bind_host), m_bind_port(bind_port) { } @@ -222,35 +222,35 @@ int GdbServer::Debug(int signal) // Load Registers { - CpuReg regs[] = { - REG_EAX, REG_ECX, REG_EDX, REG_EBX, - REG_ESP, REG_EBP, REG_ESI, REG_EDI, - REG_EIP, REG_EFLAGS, - REG_CS, REG_SS, REG_DS, REG_ES, REG_FS, REG_GS + Reg regs[] = { + Reg::EAX, Reg::ECX, Reg::EDX, Reg::EBX, + Reg::ESP, Reg::EBP, Reg::ESI, Reg::EDI, + Reg::EIP, Reg::EFLAGS, + Reg::CS, Reg::SS, Reg::DS, Reg::ES, Reg::FS, Reg::GS }; - uint32_t vals[ARRAY_SIZE(regs)]; + RegValue vals[ARRAY_SIZE(regs)]; - m_cpu->RegRead(regs, vals, ARRAY_SIZE(regs)); + m_vp.RegRead(regs, vals, ARRAY_SIZE(regs)); - m_dbg_state.registers[DBG_CPU_I386_REG_EAX] = vals[0]; - m_dbg_state.registers[DBG_CPU_I386_REG_ECX] = vals[1]; - m_dbg_state.registers[DBG_CPU_I386_REG_EDX] = vals[2]; - m_dbg_state.registers[DBG_CPU_I386_REG_EBX] = vals[3]; + m_dbg_state.registers[DBG_CPU_I386_REG_EAX] = vals[0].u32; + m_dbg_state.registers[DBG_CPU_I386_REG_ECX] = vals[1].u32; + m_dbg_state.registers[DBG_CPU_I386_REG_EDX] = vals[2].u32; + m_dbg_state.registers[DBG_CPU_I386_REG_EBX] = vals[3].u32; - m_dbg_state.registers[DBG_CPU_I386_REG_ESP] = vals[4]; - m_dbg_state.registers[DBG_CPU_I386_REG_EBP] = vals[5]; - m_dbg_state.registers[DBG_CPU_I386_REG_ESI] = vals[6]; - m_dbg_state.registers[DBG_CPU_I386_REG_EDI] = vals[7]; + m_dbg_state.registers[DBG_CPU_I386_REG_ESP] = vals[4].u32; + m_dbg_state.registers[DBG_CPU_I386_REG_EBP] = vals[5].u32; + m_dbg_state.registers[DBG_CPU_I386_REG_ESI] = vals[6].u32; + m_dbg_state.registers[DBG_CPU_I386_REG_EDI] = vals[7].u32; - m_dbg_state.registers[DBG_CPU_I386_REG_PC] = vals[8]; - m_dbg_state.registers[DBG_CPU_I386_REG_PS] = vals[9]; + m_dbg_state.registers[DBG_CPU_I386_REG_PC] = vals[8].u32; + m_dbg_state.registers[DBG_CPU_I386_REG_PS] = vals[9].u32; - m_dbg_state.registers[DBG_CPU_I386_REG_CS] = vals[10]; - m_dbg_state.registers[DBG_CPU_I386_REG_SS] = vals[11]; - m_dbg_state.registers[DBG_CPU_I386_REG_DS] = vals[12]; - m_dbg_state.registers[DBG_CPU_I386_REG_ES] = vals[13]; - m_dbg_state.registers[DBG_CPU_I386_REG_FS] = vals[14]; - m_dbg_state.registers[DBG_CPU_I386_REG_GS] = vals[15]; + m_dbg_state.registers[DBG_CPU_I386_REG_CS] = vals[10].segment.selector; + m_dbg_state.registers[DBG_CPU_I386_REG_SS] = vals[11].segment.selector; + m_dbg_state.registers[DBG_CPU_I386_REG_DS] = vals[12].segment.selector; + m_dbg_state.registers[DBG_CPU_I386_REG_ES] = vals[13].segment.selector; + m_dbg_state.registers[DBG_CPU_I386_REG_FS] = vals[14].segment.selector; + m_dbg_state.registers[DBG_CPU_I386_REG_GS] = vals[15].segment.selector; } // If interrupt was caused by a soft breakpoint (int3 = CCh), EIP will point @@ -271,12 +271,12 @@ int GdbServer::Debug(int signal) #if 1 { // Restore Registers - CpuReg regs[] = { - REG_EAX, REG_ECX, REG_EDX, REG_EBX, - REG_ESP, REG_EBP, REG_ESI, REG_EDI, - REG_EIP, REG_EFLAGS + Reg regs[] = { + Reg::EAX, Reg::ECX, Reg::EDX, Reg::EBX, + Reg::ESP, Reg::EBP, Reg::ESI, Reg::EDI, + Reg::EIP, Reg::EFLAGS }; - uint32_t vals[] = { + RegValue vals[] = { m_dbg_state.registers[DBG_CPU_I386_REG_EAX], m_dbg_state.registers[DBG_CPU_I386_REG_ECX], m_dbg_state.registers[DBG_CPU_I386_REG_EDX], @@ -291,7 +291,7 @@ int GdbServer::Debug(int signal) m_dbg_state.registers[DBG_CPU_I386_REG_PS] }; - m_cpu->RegWrite(regs, vals, ARRAY_SIZE(regs)); + m_vp.RegWrite(regs, vals, ARRAY_SIZE(regs)); } #endif @@ -353,7 +353,7 @@ int GdbServer::dbg_sys_putchar(int ch) */ int GdbServer::dbg_sys_mem_readb(address addr, char *val) { - m_cpu->VMemRead(addr, 1, val); + m_vp.LMemRead(addr, 1, val); return 0; } @@ -362,7 +362,7 @@ int GdbServer::dbg_sys_mem_readb(address addr, char *val) */ int GdbServer::dbg_sys_mem_writeb(address addr, char val) { - m_cpu->VMemWrite(addr, 1, &val); + m_vp.LMemWrite(addr, 1, &val); return 0; } diff --git a/src/core/vixen/hw/ata/ata.cpp b/modules/core/src/common/vixen/hw/ata/ata.cpp similarity index 99% rename from src/core/vixen/hw/ata/ata.cpp rename to modules/core/src/common/vixen/hw/ata/ata.cpp index 71645d4..4b1c6d5 100644 --- a/src/core/vixen/hw/ata/ata.cpp +++ b/modules/core/src/common/vixen/hw/ata/ata.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "ata.h" +#include "vixen/hw/ata/ata.h" #include "vixen/log.h" #include "vixen/io.h" diff --git a/src/core/vixen/hw/ata/ata_channel.cpp b/modules/core/src/common/vixen/hw/ata/ata_channel.cpp similarity index 99% rename from src/core/vixen/hw/ata/ata_channel.cpp rename to modules/core/src/common/vixen/hw/ata/ata_channel.cpp index 4ba53bb..9fefe23 100644 --- a/src/core/vixen/hw/ata/ata_channel.cpp +++ b/modules/core/src/common/vixen/hw/ata/ata_channel.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "ata.h" +#include "vixen/hw/ata/ata.h" #include "vixen/log.h" #include "vixen/io.h" diff --git a/src/core/vixen/hw/ata/ata_common.cpp b/modules/core/src/common/vixen/hw/ata/ata_common.cpp similarity index 96% rename from src/core/vixen/hw/ata/ata_common.cpp rename to modules/core/src/common/vixen/hw/ata/ata_common.cpp index 3197e6b..db6ff5b 100644 --- a/src/core/vixen/hw/ata/ata_common.cpp +++ b/modules/core/src/common/vixen/hw/ata/ata_common.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "ata_common.h" +#include "vixen/hw/ata/ata_common.h" namespace vixen { namespace hw { diff --git a/src/core/vixen/hw/ata/ata_device.cpp b/modules/core/src/common/vixen/hw/ata/ata_device.cpp similarity index 95% rename from src/core/vixen/hw/ata/ata_device.cpp rename to modules/core/src/common/vixen/hw/ata/ata_device.cpp index 6cf0518..4ced465 100644 --- a/src/core/vixen/hw/ata/ata_device.cpp +++ b/modules/core/src/common/vixen/hw/ata/ata_device.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "ata_device.h" +#include "vixen/hw/ata/ata_device.h" #include "vixen/log.h" #include "vixen/io.h" diff --git a/src/core/vixen/hw/ata/cmds/ata_command.cpp b/modules/core/src/common/vixen/hw/ata/cmds/ata_command.cpp similarity index 95% rename from src/core/vixen/hw/ata/cmds/ata_command.cpp rename to modules/core/src/common/vixen/hw/ata/cmds/ata_command.cpp index 3a92c6f..2e861a0 100644 --- a/src/core/vixen/hw/ata/cmds/ata_command.cpp +++ b/modules/core/src/common/vixen/hw/ata/cmds/ata_command.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "ata_command.h" +#include "vixen/hw/ata/cmds/ata_command.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/ata/cmds/cmd_identify_device.cpp b/modules/core/src/common/vixen/hw/ata/cmds/cmd_identify_device.cpp similarity index 97% rename from src/core/vixen/hw/ata/cmds/cmd_identify_device.cpp rename to modules/core/src/common/vixen/hw/ata/cmds/cmd_identify_device.cpp index f7865a9..f2088bc 100644 --- a/src/core/vixen/hw/ata/cmds/cmd_identify_device.cpp +++ b/modules/core/src/common/vixen/hw/ata/cmds/cmd_identify_device.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "cmd_identify_device.h" +#include "vixen/hw/ata/cmds/cmd_identify_device.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/ata/cmds/cmd_identify_packet_device.cpp b/modules/core/src/common/vixen/hw/ata/cmds/cmd_identify_packet_device.cpp similarity index 97% rename from src/core/vixen/hw/ata/cmds/cmd_identify_packet_device.cpp rename to modules/core/src/common/vixen/hw/ata/cmds/cmd_identify_packet_device.cpp index 339c15e..f925247 100644 --- a/src/core/vixen/hw/ata/cmds/cmd_identify_packet_device.cpp +++ b/modules/core/src/common/vixen/hw/ata/cmds/cmd_identify_packet_device.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "cmd_identify_packet_device.h" +#include "vixen/hw/ata/cmds/cmd_identify_packet_device.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/ata/cmds/cmd_init_dev_params.cpp b/modules/core/src/common/vixen/hw/ata/cmds/cmd_init_dev_params.cpp similarity index 98% rename from src/core/vixen/hw/ata/cmds/cmd_init_dev_params.cpp rename to modules/core/src/common/vixen/hw/ata/cmds/cmd_init_dev_params.cpp index 388ab7f..896f809 100644 --- a/src/core/vixen/hw/ata/cmds/cmd_init_dev_params.cpp +++ b/modules/core/src/common/vixen/hw/ata/cmds/cmd_init_dev_params.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "cmd_init_dev_params.h" +#include "vixen/hw/ata/cmds/cmd_init_dev_params.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/ata/cmds/cmd_packet.cpp b/modules/core/src/common/vixen/hw/ata/cmds/cmd_packet.cpp similarity index 94% rename from src/core/vixen/hw/ata/cmds/cmd_packet.cpp rename to modules/core/src/common/vixen/hw/ata/cmds/cmd_packet.cpp index 8c695d5..7ece1e4 100644 --- a/src/core/vixen/hw/ata/cmds/cmd_packet.cpp +++ b/modules/core/src/common/vixen/hw/ata/cmds/cmd_packet.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "cmd_packet.h" +#include "vixen/hw/ata/cmds/cmd_packet.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/ata/cmds/cmd_read_dma.cpp b/modules/core/src/common/vixen/hw/ata/cmds/cmd_read_dma.cpp similarity index 93% rename from src/core/vixen/hw/ata/cmds/cmd_read_dma.cpp rename to modules/core/src/common/vixen/hw/ata/cmds/cmd_read_dma.cpp index f3bf77d..6d5d6ff 100644 --- a/src/core/vixen/hw/ata/cmds/cmd_read_dma.cpp +++ b/modules/core/src/common/vixen/hw/ata/cmds/cmd_read_dma.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "cmd_read_dma.h" +#include "vixen/hw/ata/cmds/cmd_read_dma.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/ata/cmds/cmd_security_unlock.cpp b/modules/core/src/common/vixen/hw/ata/cmds/cmd_security_unlock.cpp similarity index 95% rename from src/core/vixen/hw/ata/cmds/cmd_security_unlock.cpp rename to modules/core/src/common/vixen/hw/ata/cmds/cmd_security_unlock.cpp index 7f0a469..9998aad 100644 --- a/src/core/vixen/hw/ata/cmds/cmd_security_unlock.cpp +++ b/modules/core/src/common/vixen/hw/ata/cmds/cmd_security_unlock.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "cmd_security_unlock.h" +#include "vixen/hw/ata/cmds/cmd_security_unlock.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/ata/cmds/cmd_set_features.cpp b/modules/core/src/common/vixen/hw/ata/cmds/cmd_set_features.cpp similarity index 99% rename from src/core/vixen/hw/ata/cmds/cmd_set_features.cpp rename to modules/core/src/common/vixen/hw/ata/cmds/cmd_set_features.cpp index 4e29947..90f89ec 100644 --- a/src/core/vixen/hw/ata/cmds/cmd_set_features.cpp +++ b/modules/core/src/common/vixen/hw/ata/cmds/cmd_set_features.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "cmd_set_features.h" +#include "vixen/hw/ata/cmds/cmd_set_features.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/ata/cmds/cmd_write_dma.cpp b/modules/core/src/common/vixen/hw/ata/cmds/cmd_write_dma.cpp similarity index 93% rename from src/core/vixen/hw/ata/cmds/cmd_write_dma.cpp rename to modules/core/src/common/vixen/hw/ata/cmds/cmd_write_dma.cpp index 94088cf..7bcd9ad 100644 --- a/src/core/vixen/hw/ata/cmds/cmd_write_dma.cpp +++ b/modules/core/src/common/vixen/hw/ata/cmds/cmd_write_dma.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "cmd_write_dma.h" +#include "vixen/hw/ata/cmds/cmd_write_dma.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/ata/cmds/proto_dma.cpp b/modules/core/src/common/vixen/hw/ata/cmds/proto_dma.cpp similarity index 99% rename from src/core/vixen/hw/ata/cmds/proto_dma.cpp rename to modules/core/src/common/vixen/hw/ata/cmds/proto_dma.cpp index 7a6a59a..c845bbd 100644 --- a/src/core/vixen/hw/ata/cmds/proto_dma.cpp +++ b/modules/core/src/common/vixen/hw/ata/cmds/proto_dma.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "proto_dma.h" +#include "vixen/hw/ata/cmds/proto_dma.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/ata/cmds/proto_nondata.cpp b/modules/core/src/common/vixen/hw/ata/cmds/proto_nondata.cpp similarity index 96% rename from src/core/vixen/hw/ata/cmds/proto_nondata.cpp rename to modules/core/src/common/vixen/hw/ata/cmds/proto_nondata.cpp index df38b95..cdccb65 100644 --- a/src/core/vixen/hw/ata/cmds/proto_nondata.cpp +++ b/modules/core/src/common/vixen/hw/ata/cmds/proto_nondata.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "proto_nondata.h" +#include "vixen/hw/ata/cmds/proto_nondata.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/ata/cmds/proto_packet.cpp b/modules/core/src/common/vixen/hw/ata/cmds/proto_packet.cpp similarity index 97% rename from src/core/vixen/hw/ata/cmds/proto_packet.cpp rename to modules/core/src/common/vixen/hw/ata/cmds/proto_packet.cpp index e9b668d..657a996 100644 --- a/src/core/vixen/hw/ata/cmds/proto_packet.cpp +++ b/modules/core/src/common/vixen/hw/ata/cmds/proto_packet.cpp @@ -1,368 +1,368 @@ -// ATA/ATAPI-4 emulation for the Original Xbox -// (C) Ivan "StrikerX3" Oliveira -// -// This code aims to implement a subset of the ATA/ATAPI-4 specification -// that satisifies the requirements of an IDE interface for the Original Xbox. -// -// Specification: -// http://www.t13.org/documents/UploadedDocuments/project/d1153r18-ATA-ATAPI-4.pdf -// -// References to particular items in the specification are denoted between brackets -// optionally followed by a quote from the specification. -#include "proto_packet.h" - -#include "vixen/log.h" -#include "vixen/hw/atapi/atapi_defs.h" -#include "vixen/hw/atapi/atapi_xbox.h" -#include "vixen/hw/atapi/atapi_utils.h" -#include "vixen/hw/atapi/cmds/atapi_command.h" - -namespace vixen { -namespace hw { -namespace ata { -namespace cmd { - -using namespace vixen::hw::atapi; - -// Notes regarding the protocol: -// - There are two fluxograms: PIO/non-data transfers and DMA transfers -// - They're largely the same, except for the actual data transfer and some register flag manipulations -// -// - The Sector Count register is called the Interrupt Reason register -// - The Cylinder Low/High registers are called Byte Count Low/High registers -// - The Features register contains the following fields: -// bit 1 (OVL) Indicates an overlapped command -// bit 0 (DMA) Use DMA for data transfer (not for the Packet command itself) -// - The Interrupt Reason register contains the following fields: -// bit 7..3 (Tag) (Overlapped only) Command tag -// bit 2 (REL) (Overlapped only) Indicates that the device is performing a bus release -// bit 1 (I/O) When set to 1, indicates a transfer to the host; 0 indicates transfer to the device -// bit 0 (C/D) When set to 1, indicates a command packet; 0 indicates a data packet -// - The Status register includes the following fields: -// bit 5 (DMRD) DMA ready -// bit 4 (SERV) (Overlapped only) Indicates that another command can be serviced -// bit 0 (CHK) Indicates an error; host should check the Error register sense key or code bit -// -// Overlapped commands allow the device to execute a long-running operation in the background -// while still accepting new packet commands. - -PacketProtocolCommand::PacketProtocolCommand(ATADevice& device) - : IATACommand(device) - , m_packetCmdBuffer(nullptr) - , m_command(nullptr) -{ -} - -PacketProtocolCommand::~PacketProtocolCommand() { - if (m_packetCmdBuffer != nullptr) { - delete[] m_packetCmdBuffer; - } - if (m_command != nullptr) { - delete m_command; - } -} - -void PacketProtocolCommand::Execute() { - // Read input according to the protocol [8.21.4] - m_packetCmdState.input.overlapped = !!(m_regs.features & PkFeatOverlapped); - m_packetCmdState.input.dmaTransfer = !!(m_regs.features & PkFeatDMATransfer); - m_packetCmdState.input.tag = (m_regs.sectorCount >> kPkTagShift) & kPkTagMask; - m_packetCmdState.input.byteCountLimit = m_regs.cylinder; - m_packetCmdState.input.selectedDevice = m_regs.GetSelectedDeviceIndex(); - - // If the byte count limit is zero, set ABRT and stop command - if (m_packetCmdState.input.byteCountLimit == 0) { - m_regs.error |= ErrAbort; - HandleProtocolTail(true); - return; - } - - // A byte count limit of 0xFFFF is interpreted by the device as though it were 0xFFFE - if (m_packetCmdState.input.byteCountLimit == 0xFFFF) { - m_packetCmdState.input.byteCountLimit = 0xFFFE; - } - - // Update Interrupt register - m_regs.sectorCount |= PkIntrCmdOrData; - m_regs.sectorCount &= ~PkIntrIODirection; - // On PIO and non-data transfers, Bus Release is cleared - if (!m_packetCmdState.input.dmaTransfer) { - m_regs.sectorCount &= ~PkIntrBusRelease; - } - - // Update Status register - m_regs.status |= StDataRequest; - m_regs.status &= ~StBusy; - - // Allocate buffer for the packet - m_packetCmdBuffer = new uint8_t[m_driver->GetPacketCommandSize()]; - m_packetCmdPos = 0; - - // Follow (A) in the protocol fluxogram -} - -void PacketProtocolCommand::ReadData(uint8_t *value, uint32_t size) { - // Host is reading the data requested by the Packet command - - uint32_t pos = 0; - - do { - // Read from buffer - uint32_t sizeRead = m_packetCmdState.dataBuffer.Read(value + pos, size - pos); - pos += sizeRead; - - // Done reading the packet data? - if (m_packetCmdState.dataBuffer.IsReadFinished()) { - m_regs.status |= StBusy; - m_regs.status &= ~StDataRequest; - - // Done transferring all the data needed by the packet? - if (m_command->IsTransferFinished()) { - HandleProtocolTail(false); - return; - } - - // Read more data - if (!m_command->Execute()) { - HandleProtocolTail(true); - return; - } - } - } while (pos < size); -} - -void PacketProtocolCommand::WriteData(uint8_t *value, uint32_t size) { - // Determine if the host is writing the Packet command itself or the data it requested - if (m_regs.sectorCount & PkIntrCmdOrData) { - // Writing the Packet command itself - memcpy(m_packetCmdBuffer + m_packetCmdPos, value, size); - m_packetCmdPos += size; - - // Done writing the Packet command? - if (m_packetCmdPos >= m_driver->GetPacketCommandSize()) { - ProcessPacket(); - } - } - else { - // Writing the data requested by the Packet command - - uint32_t pos = 0; - - do { - // Write to buffer - uint32_t sizeWritten = m_packetCmdState.dataBuffer.Write(value, size); - pos += sizeWritten; - - // Done writing the packet data? - if (m_packetCmdState.dataBuffer.IsWriteFinished()) { - m_regs.status |= StBusy; - m_regs.status &= ~StDataRequest; - - // Execute command with the current buffer - if (!m_command->Execute()) { - HandleProtocolTail(true); - return; - } - - // Done transferring all the data needed by the packet? - if (m_command->IsTransferFinished()) { - HandleProtocolTail(false); - return; - } - } - } while (pos < size); - } -} - -void PacketProtocolCommand::ProcessPacket() { - //log_spew("PacketProtocolCommand::ProcessPacket: Processing packet\n"); - m_regs.status |= StBusy; - m_regs.status &= ~StDataRequest; - - // Get the command descriptor block - atapi::CommandDescriptorBlock *cdb = reinterpret_cast(m_packetCmdBuffer); - - // Get the command factory for the command's operation code - if (kCmdFactories.count(cdb->opCode.u8) == 0) { - log_warning("PacketProtocolCommand::ProcessPacket: Unimplemented command 0x%x!\n", cdb->opCode.u8); - HandleProtocolTail(true); - return; - } - - //log_spew("PacketProtocolCommand::ProcessPacket: Processing command 0x%x\n", cdb->opCode.u8); - - // Instantiate the command. - // This will also allocate the data buffer if necessary. - m_packetCmdState.cdb = *cdb; - auto factory = kCmdFactories.at(cdb->opCode.u8); - m_command = factory(m_packetCmdState, m_driver); - - // Validate parameters; return error immediately if invalid. - // Will also initialize the data buffer if a transfer is required. - if (!m_command->Prepare()) { - HandleProtocolTail(true); - return; - } - - if (m_command->GetOperationType() == PktOpNonData) { - // Execute non-data command immediately - bool succeeded = m_command->Execute(); - HandleProtocolTail(!succeeded); - } - else { - // Prepare registers for a data transfer (in or out) - PrepareDataTransfer(); - } -} - -void PacketProtocolCommand::PrepareDataTransfer() { - // Check for overlapped execution (corresponds to (B) in the protocol fluxogram) - if (m_driver->SupportsOverlap() && m_driver->IsOverlapEnabled() && m_packetCmdState.input.overlapped) { - ProcessPacketOverlapped(); - } - else { - ProcessPacketImmediate(); - } -} - -void PacketProtocolCommand::ProcessPacketImmediate() { - if (m_packetCmdState.input.dmaTransfer) { - m_regs.sectorCount &= ~PkIntrBusRelease; - m_regs.status &= ~StService; - m_regs.status |= StDMAReady; - } - else { - // Set Tag - m_regs.sectorCount &= ~(kPkTagMask << kPkTagShift); - m_regs.sectorCount |= m_packetCmdState.input.tag << kPkTagShift; - - // Set byte count - m_regs.cylinder = m_packetCmdState.input.byteCountLimit; - } - - // Set I/O - if (m_command->GetOperationType() == atapi::PktOpDataOut) { - m_regs.sectorCount |= PkIntrIODirection; - } - else { - m_regs.sectorCount &= ~PkIntrIODirection; - } - - // Clear C/D=0 - m_regs.sectorCount &= ~PkIntrCmdOrData; - - // Update Status register - m_regs.status |= StDataRequest; - m_regs.status &= ~StBusy; - - // Only assert INTRQ on PIO transfers - if (!m_packetCmdState.input.dmaTransfer) { - m_interrupt.Assert(); - } -} - -void PacketProtocolCommand::ProcessPacketOverlapped() { - // TODO: implement (F) - log_warning("PacketProtocolCommand::ProcessPacketOverlapped: Unimplemented!\n"); -} - -void PacketProtocolCommand::HandleProtocolTail(bool hasError) { - if (hasError) { - m_regs.status |= StError; - - // Fill in error output according to the protocol [8.21.6] - - // Error register: - // "Sense Key is a command packet set specific error indication." - m_regs.error &= ~(kPkSenseMask << kPkSenseShift); - m_regs.error |= (m_packetCmdState.result.senseKey & kPkSenseMask) << kPkSenseShift; - - // "ABRT shall be set to one if the requested command has been command - // [sic] aborted because the command code or a command parameter is - // invalid. ABRT may be set to one if the device is not able to - // complete the action requested by the command." - if (m_packetCmdState.result.aborted) { - m_regs.error |= ErrAbort; - } - else { - m_regs.error &= ~ErrAbort; - } - - // "EOM - the meaning of this bit is command set specific. See the - // appropriate command set standard for its definition." - if (m_packetCmdState.result.endOfMedium) { - m_regs.error |= PkErrEndOfMedium; - } - else { - m_regs.error &= ~PkErrEndOfMedium; - } - - // "ILI - the meaning of this bit is command set specific. See the - // appropriate command set standard for its definition." - if (m_packetCmdState.result.incorrectLength) { - m_regs.error |= PkErrIncorrectLength; - } - else { - m_regs.error &= ~PkErrIncorrectLength; - } - - // Interrupt reason register: - // "Tag - If the device supports command queuing and overlap is - // enabled, this field contains the command Tag for the command. - // If the device does not support command queuing or overlap is - // disabled, this field is not applicable." - // We'll fill it in regardless of command queuing or overlap support - m_regs.sectorCount &= ~(kPkTagMask << kPkTagShift); - m_regs.sectorCount |= m_packetCmdState.input.tag << kPkTagShift; - - // "REL - Shall be cleared to zero." - m_regs.sectorCount &= ~PkIntrBusRelease; - - // "I/O - Shall be set to one." - // "C/D - Shall be set to one." - // Done below - - // Device/Head register: - // "DEV shall indicate the selected device." - // Not necessary, but the spec says so - m_regs.deviceHead = (m_regs.deviceHead & ~(1 << kDevSelectorBit)) | (m_devIndex << kDevSelectorBit); - - // Status register: - // "BSY shall be cleared to zero indicating command completion." - // "DRDY shall be set to one." - // "DRQ shall be cleared to zero." - // Done below - - // "SERV(Service) - Shall be set to one if another command is ready to be serviced. - // If overlap is not supported, this bit is command specific." - // TODO: support overlapped operations - - // "DF(Device Fault) shall be set to one if a device fault has occurred." - if (m_packetCmdState.result.deviceFault) { - m_regs.status |= StDeviceFault; - } - - // "CHK shall be set to one if an Error register sense key or code bit is set." - if (m_regs.error) { - m_regs.status |= StCheck; - } - } - - // The Sector Count register is called the Interrupt register on the Packet protocol - m_regs.sectorCount |= PkIntrIODirection | PkIntrCmdOrData; - m_regs.sectorCount &= ~PkIntrBusRelease; - - if (m_packetCmdState.input.dmaTransfer) { - m_regs.status &= ~StDataRequest; - } - m_regs.status |= StReady; - m_regs.status &= ~StBusy; - m_interrupt.Assert(); - //log_spew("PacketProtocolCommand::HandleProtocolTail: Packet command finished\n"); - Finish(); -} - -} -} -} -} +// ATA/ATAPI-4 emulation for the Original Xbox +// (C) Ivan "StrikerX3" Oliveira +// +// This code aims to implement a subset of the ATA/ATAPI-4 specification +// that satisifies the requirements of an IDE interface for the Original Xbox. +// +// Specification: +// http://www.t13.org/documents/UploadedDocuments/project/d1153r18-ATA-ATAPI-4.pdf +// +// References to particular items in the specification are denoted between brackets +// optionally followed by a quote from the specification. +#include "vixen/hw/ata/cmds/proto_packet.h" + +#include "vixen/log.h" +#include "vixen/hw/atapi/atapi_defs.h" +#include "vixen/hw/atapi/atapi_xbox.h" +#include "vixen/hw/atapi/atapi_utils.h" +#include "vixen/hw/atapi/cmds/atapi_command.h" + +namespace vixen { +namespace hw { +namespace ata { +namespace cmd { + +using namespace vixen::hw::atapi; + +// Notes regarding the protocol: +// - There are two fluxograms: PIO/non-data transfers and DMA transfers +// - They're largely the same, except for the actual data transfer and some register flag manipulations +// +// - The Sector Count register is called the Interrupt Reason register +// - The Cylinder Low/High registers are called Byte Count Low/High registers +// - The Features register contains the following fields: +// bit 1 (OVL) Indicates an overlapped command +// bit 0 (DMA) Use DMA for data transfer (not for the Packet command itself) +// - The Interrupt Reason register contains the following fields: +// bit 7..3 (Tag) (Overlapped only) Command tag +// bit 2 (REL) (Overlapped only) Indicates that the device is performing a bus release +// bit 1 (I/O) When set to 1, indicates a transfer to the host; 0 indicates transfer to the device +// bit 0 (C/D) When set to 1, indicates a command packet; 0 indicates a data packet +// - The Status register includes the following fields: +// bit 5 (DMRD) DMA ready +// bit 4 (SERV) (Overlapped only) Indicates that another command can be serviced +// bit 0 (CHK) Indicates an error; host should check the Error register sense key or code bit +// +// Overlapped commands allow the device to execute a long-running operation in the background +// while still accepting new packet commands. + +PacketProtocolCommand::PacketProtocolCommand(ATADevice& device) + : IATACommand(device) + , m_packetCmdBuffer(nullptr) + , m_command(nullptr) +{ +} + +PacketProtocolCommand::~PacketProtocolCommand() { + if (m_packetCmdBuffer != nullptr) { + delete[] m_packetCmdBuffer; + } + if (m_command != nullptr) { + delete m_command; + } +} + +void PacketProtocolCommand::Execute() { + // Read input according to the protocol [8.21.4] + m_packetCmdState.input.overlapped = !!(m_regs.features & PkFeatOverlapped); + m_packetCmdState.input.dmaTransfer = !!(m_regs.features & PkFeatDMATransfer); + m_packetCmdState.input.tag = (m_regs.sectorCount >> kPkTagShift) & kPkTagMask; + m_packetCmdState.input.byteCountLimit = m_regs.cylinder; + m_packetCmdState.input.selectedDevice = m_regs.GetSelectedDeviceIndex(); + + // If the byte count limit is zero, set ABRT and stop command + if (m_packetCmdState.input.byteCountLimit == 0) { + m_regs.error |= ErrAbort; + HandleProtocolTail(true); + return; + } + + // A byte count limit of 0xFFFF is interpreted by the device as though it were 0xFFFE + if (m_packetCmdState.input.byteCountLimit == 0xFFFF) { + m_packetCmdState.input.byteCountLimit = 0xFFFE; + } + + // Update Interrupt register + m_regs.sectorCount |= PkIntrCmdOrData; + m_regs.sectorCount &= ~PkIntrIODirection; + // On PIO and non-data transfers, Bus Release is cleared + if (!m_packetCmdState.input.dmaTransfer) { + m_regs.sectorCount &= ~PkIntrBusRelease; + } + + // Update Status register + m_regs.status |= StDataRequest; + m_regs.status &= ~StBusy; + + // Allocate buffer for the packet + m_packetCmdBuffer = new uint8_t[m_driver->GetPacketCommandSize()]; + m_packetCmdPos = 0; + + // Follow (A) in the protocol fluxogram +} + +void PacketProtocolCommand::ReadData(uint8_t *value, uint32_t size) { + // Host is reading the data requested by the Packet command + + uint32_t pos = 0; + + do { + // Read from buffer + uint32_t sizeRead = m_packetCmdState.dataBuffer.Read(value + pos, size - pos); + pos += sizeRead; + + // Done reading the packet data? + if (m_packetCmdState.dataBuffer.IsReadFinished()) { + m_regs.status |= StBusy; + m_regs.status &= ~StDataRequest; + + // Done transferring all the data needed by the packet? + if (m_command->IsTransferFinished()) { + HandleProtocolTail(false); + return; + } + + // Read more data + if (!m_command->Execute()) { + HandleProtocolTail(true); + return; + } + } + } while (pos < size); +} + +void PacketProtocolCommand::WriteData(uint8_t *value, uint32_t size) { + // Determine if the host is writing the Packet command itself or the data it requested + if (m_regs.sectorCount & PkIntrCmdOrData) { + // Writing the Packet command itself + memcpy(m_packetCmdBuffer + m_packetCmdPos, value, size); + m_packetCmdPos += size; + + // Done writing the Packet command? + if (m_packetCmdPos >= m_driver->GetPacketCommandSize()) { + ProcessPacket(); + } + } + else { + // Writing the data requested by the Packet command + + uint32_t pos = 0; + + do { + // Write to buffer + uint32_t sizeWritten = m_packetCmdState.dataBuffer.Write(value, size); + pos += sizeWritten; + + // Done writing the packet data? + if (m_packetCmdState.dataBuffer.IsWriteFinished()) { + m_regs.status |= StBusy; + m_regs.status &= ~StDataRequest; + + // Execute command with the current buffer + if (!m_command->Execute()) { + HandleProtocolTail(true); + return; + } + + // Done transferring all the data needed by the packet? + if (m_command->IsTransferFinished()) { + HandleProtocolTail(false); + return; + } + } + } while (pos < size); + } +} + +void PacketProtocolCommand::ProcessPacket() { + //log_spew("PacketProtocolCommand::ProcessPacket: Processing packet\n"); + m_regs.status |= StBusy; + m_regs.status &= ~StDataRequest; + + // Get the command descriptor block + atapi::CommandDescriptorBlock *cdb = reinterpret_cast(m_packetCmdBuffer); + + // Get the command factory for the command's operation code + if (kCmdFactories.count(cdb->opCode.u8) == 0) { + log_warning("PacketProtocolCommand::ProcessPacket: Unimplemented command 0x%x!\n", cdb->opCode.u8); + HandleProtocolTail(true); + return; + } + + //log_spew("PacketProtocolCommand::ProcessPacket: Processing command 0x%x\n", cdb->opCode.u8); + + // Instantiate the command. + // This will also allocate the data buffer if necessary. + m_packetCmdState.cdb = *cdb; + auto factory = kCmdFactories.at(cdb->opCode.u8); + m_command = factory(m_packetCmdState, m_driver); + + // Validate parameters; return error immediately if invalid. + // Will also initialize the data buffer if a transfer is required. + if (!m_command->Prepare()) { + HandleProtocolTail(true); + return; + } + + if (m_command->GetOperationType() == PktOpNonData) { + // Execute non-data command immediately + bool succeeded = m_command->Execute(); + HandleProtocolTail(!succeeded); + } + else { + // Prepare registers for a data transfer (in or out) + PrepareDataTransfer(); + } +} + +void PacketProtocolCommand::PrepareDataTransfer() { + // Check for overlapped execution (corresponds to (B) in the protocol fluxogram) + if (m_driver->SupportsOverlap() && m_driver->IsOverlapEnabled() && m_packetCmdState.input.overlapped) { + ProcessPacketOverlapped(); + } + else { + ProcessPacketImmediate(); + } +} + +void PacketProtocolCommand::ProcessPacketImmediate() { + if (m_packetCmdState.input.dmaTransfer) { + m_regs.sectorCount &= ~PkIntrBusRelease; + m_regs.status &= ~StService; + m_regs.status |= StDMAReady; + } + else { + // Set Tag + m_regs.sectorCount &= ~(kPkTagMask << kPkTagShift); + m_regs.sectorCount |= m_packetCmdState.input.tag << kPkTagShift; + + // Set byte count + m_regs.cylinder = m_packetCmdState.input.byteCountLimit; + } + + // Set I/O + if (m_command->GetOperationType() == atapi::PktOpDataOut) { + m_regs.sectorCount |= PkIntrIODirection; + } + else { + m_regs.sectorCount &= ~PkIntrIODirection; + } + + // Clear C/D=0 + m_regs.sectorCount &= ~PkIntrCmdOrData; + + // Update Status register + m_regs.status |= StDataRequest; + m_regs.status &= ~StBusy; + + // Only assert INTRQ on PIO transfers + if (!m_packetCmdState.input.dmaTransfer) { + m_interrupt.Assert(); + } +} + +void PacketProtocolCommand::ProcessPacketOverlapped() { + // TODO: implement (F) + log_warning("PacketProtocolCommand::ProcessPacketOverlapped: Unimplemented!\n"); +} + +void PacketProtocolCommand::HandleProtocolTail(bool hasError) { + if (hasError) { + m_regs.status |= StError; + + // Fill in error output according to the protocol [8.21.6] + + // Error register: + // "Sense Key is a command packet set specific error indication." + m_regs.error &= ~(kPkSenseMask << kPkSenseShift); + m_regs.error |= (m_packetCmdState.result.senseKey & kPkSenseMask) << kPkSenseShift; + + // "ABRT shall be set to one if the requested command has been command + // [sic] aborted because the command code or a command parameter is + // invalid. ABRT may be set to one if the device is not able to + // complete the action requested by the command." + if (m_packetCmdState.result.aborted) { + m_regs.error |= ErrAbort; + } + else { + m_regs.error &= ~ErrAbort; + } + + // "EOM - the meaning of this bit is command set specific. See the + // appropriate command set standard for its definition." + if (m_packetCmdState.result.endOfMedium) { + m_regs.error |= PkErrEndOfMedium; + } + else { + m_regs.error &= ~PkErrEndOfMedium; + } + + // "ILI - the meaning of this bit is command set specific. See the + // appropriate command set standard for its definition." + if (m_packetCmdState.result.incorrectLength) { + m_regs.error |= PkErrIncorrectLength; + } + else { + m_regs.error &= ~PkErrIncorrectLength; + } + + // Interrupt reason register: + // "Tag - If the device supports command queuing and overlap is + // enabled, this field contains the command Tag for the command. + // If the device does not support command queuing or overlap is + // disabled, this field is not applicable." + // We'll fill it in regardless of command queuing or overlap support + m_regs.sectorCount &= ~(kPkTagMask << kPkTagShift); + m_regs.sectorCount |= m_packetCmdState.input.tag << kPkTagShift; + + // "REL - Shall be cleared to zero." + m_regs.sectorCount &= ~PkIntrBusRelease; + + // "I/O - Shall be set to one." + // "C/D - Shall be set to one." + // Done below + + // Device/Head register: + // "DEV shall indicate the selected device." + // Not necessary, but the spec says so + m_regs.deviceHead = (m_regs.deviceHead & ~(1 << kDevSelectorBit)) | (m_devIndex << kDevSelectorBit); + + // Status register: + // "BSY shall be cleared to zero indicating command completion." + // "DRDY shall be set to one." + // "DRQ shall be cleared to zero." + // Done below + + // "SERV(Service) - Shall be set to one if another command is ready to be serviced. + // If overlap is not supported, this bit is command specific." + // TODO: support overlapped operations + + // "DF(Device Fault) shall be set to one if a device fault has occurred." + if (m_packetCmdState.result.deviceFault) { + m_regs.status |= StDeviceFault; + } + + // "CHK shall be set to one if an Error register sense key or code bit is set." + if (m_regs.error) { + m_regs.status |= StCheck; + } + } + + // The Sector Count register is called the Interrupt register on the Packet protocol + m_regs.sectorCount |= PkIntrIODirection | PkIntrCmdOrData; + m_regs.sectorCount &= ~PkIntrBusRelease; + + if (m_packetCmdState.input.dmaTransfer) { + m_regs.status &= ~StDataRequest; + } + m_regs.status |= StReady; + m_regs.status &= ~StBusy; + m_interrupt.Assert(); + //log_spew("PacketProtocolCommand::HandleProtocolTail: Packet command finished\n"); + Finish(); +} + +} +} +} +} diff --git a/src/core/vixen/hw/ata/cmds/proto_pio_data_in.cpp b/modules/core/src/common/vixen/hw/ata/cmds/proto_pio_data_in.cpp similarity index 98% rename from src/core/vixen/hw/ata/cmds/proto_pio_data_in.cpp rename to modules/core/src/common/vixen/hw/ata/cmds/proto_pio_data_in.cpp index 72f7403..e110f54 100644 --- a/src/core/vixen/hw/ata/cmds/proto_pio_data_in.cpp +++ b/modules/core/src/common/vixen/hw/ata/cmds/proto_pio_data_in.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "proto_pio_data_in.h" +#include "vixen/hw/ata/cmds/proto_pio_data_in.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/ata/cmds/proto_pio_data_out.cpp b/modules/core/src/common/vixen/hw/ata/cmds/proto_pio_data_out.cpp similarity index 98% rename from src/core/vixen/hw/ata/cmds/proto_pio_data_out.cpp rename to modules/core/src/common/vixen/hw/ata/cmds/proto_pio_data_out.cpp index 9bfdc7b..2034ac5 100644 --- a/src/core/vixen/hw/ata/cmds/proto_pio_data_out.cpp +++ b/modules/core/src/common/vixen/hw/ata/cmds/proto_pio_data_out.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "proto_pio_data_out.h" +#include "vixen/hw/ata/cmds/proto_pio_data_out.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/ata/drvs/ata_device_driver.cpp b/modules/core/src/common/vixen/hw/ata/drvs/ata_device_driver.cpp similarity index 94% rename from src/core/vixen/hw/ata/drvs/ata_device_driver.cpp rename to modules/core/src/common/vixen/hw/ata/drvs/ata_device_driver.cpp index c41c221..d1ac8c6 100644 --- a/src/core/vixen/hw/ata/drvs/ata_device_driver.cpp +++ b/modules/core/src/common/vixen/hw/ata/drvs/ata_device_driver.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "ata_device_driver.h" +#include "vixen/hw/ata/drvs/ata_device_driver.h" #include "vixen/log.h" #include "vixen/io.h" diff --git a/src/core/vixen/hw/ata/drvs/drv_null.cpp b/modules/core/src/common/vixen/hw/ata/drvs/drv_null.cpp similarity index 95% rename from src/core/vixen/hw/ata/drvs/drv_null.cpp rename to modules/core/src/common/vixen/hw/ata/drvs/drv_null.cpp index 38ff199..40184e5 100644 --- a/src/core/vixen/hw/ata/drvs/drv_null.cpp +++ b/modules/core/src/common/vixen/hw/ata/drvs/drv_null.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "drv_null.h" +#include "vixen/hw/ata/drvs/drv_null.h" #include "vixen/log.h" #include "vixen/io.h" diff --git a/src/core/vixen/hw/ata/drvs/drv_vdvd_base.cpp b/modules/core/src/common/vixen/hw/ata/drvs/drv_vdvd_base.cpp similarity index 99% rename from src/core/vixen/hw/ata/drvs/drv_vdvd_base.cpp rename to modules/core/src/common/vixen/hw/ata/drvs/drv_vdvd_base.cpp index 4594613..c46eae4 100644 --- a/src/core/vixen/hw/ata/drvs/drv_vdvd_base.cpp +++ b/modules/core/src/common/vixen/hw/ata/drvs/drv_vdvd_base.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "drv_vdvd_base.h" +#include "vixen/hw/ata/drvs/drv_vdvd_base.h" #include "vixen/log.h" #include "vixen/io.h" diff --git a/src/core/vixen/hw/ata/drvs/drv_vdvd_dummy.cpp b/modules/core/src/common/vixen/hw/ata/drvs/drv_vdvd_dummy.cpp similarity index 95% rename from src/core/vixen/hw/ata/drvs/drv_vdvd_dummy.cpp rename to modules/core/src/common/vixen/hw/ata/drvs/drv_vdvd_dummy.cpp index 9a1bb8b..9e316bb 100644 --- a/src/core/vixen/hw/ata/drvs/drv_vdvd_dummy.cpp +++ b/modules/core/src/common/vixen/hw/ata/drvs/drv_vdvd_dummy.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "drv_vdvd_dummy.h" +#include "vixen/hw/ata/drvs/drv_vdvd_dummy.h" #include "vixen/log.h" #include "vixen/io.h" diff --git a/src/core/vixen/hw/ata/drvs/drv_vdvd_image.cpp b/modules/core/src/common/vixen/hw/ata/drvs/drv_vdvd_image.cpp similarity index 98% rename from src/core/vixen/hw/ata/drvs/drv_vdvd_image.cpp rename to modules/core/src/common/vixen/hw/ata/drvs/drv_vdvd_image.cpp index 153d804..4d659fb 100644 --- a/src/core/vixen/hw/ata/drvs/drv_vdvd_image.cpp +++ b/modules/core/src/common/vixen/hw/ata/drvs/drv_vdvd_image.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "drv_vdvd_image.h" +#include "vixen/hw/ata/drvs/drv_vdvd_image.h" #include "vixen/log.h" #include "vixen/io.h" diff --git a/src/core/vixen/hw/ata/drvs/drv_vhd_base.cpp b/modules/core/src/common/vixen/hw/ata/drvs/drv_vhd_base.cpp similarity index 99% rename from src/core/vixen/hw/ata/drvs/drv_vhd_base.cpp rename to modules/core/src/common/vixen/hw/ata/drvs/drv_vhd_base.cpp index 6ba611e..9ef6cca 100644 --- a/src/core/vixen/hw/ata/drvs/drv_vhd_base.cpp +++ b/modules/core/src/common/vixen/hw/ata/drvs/drv_vhd_base.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "drv_vhd_base.h" +#include "vixen/hw/ata/drvs/drv_vhd_base.h" #include "vixen/log.h" #include "vixen/io.h" diff --git a/src/core/vixen/hw/ata/drvs/drv_vhd_dummy.cpp b/modules/core/src/common/vixen/hw/ata/drvs/drv_vhd_dummy.cpp similarity index 97% rename from src/core/vixen/hw/ata/drvs/drv_vhd_dummy.cpp rename to modules/core/src/common/vixen/hw/ata/drvs/drv_vhd_dummy.cpp index 0e6602f..2054174 100644 --- a/src/core/vixen/hw/ata/drvs/drv_vhd_dummy.cpp +++ b/modules/core/src/common/vixen/hw/ata/drvs/drv_vhd_dummy.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "drv_vhd_dummy.h" +#include "vixen/hw/ata/drvs/drv_vhd_dummy.h" #include "vixen/log.h" #include "vixen/io.h" diff --git a/src/core/vixen/hw/ata/drvs/drv_vhd_image.cpp b/modules/core/src/common/vixen/hw/ata/drvs/drv_vhd_image.cpp similarity index 99% rename from src/core/vixen/hw/ata/drvs/drv_vhd_image.cpp rename to modules/core/src/common/vixen/hw/ata/drvs/drv_vhd_image.cpp index 4b928a4..9db84d2 100644 --- a/src/core/vixen/hw/ata/drvs/drv_vhd_image.cpp +++ b/modules/core/src/common/vixen/hw/ata/drvs/drv_vhd_image.cpp @@ -9,7 +9,7 @@ // // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. -#include "drv_vhd_image.h" +#include "vixen/hw/ata/drvs/drv_vhd_image.h" #include "vixen/log.h" #include "vixen/io.h" diff --git a/src/core/vixen/hw/ata/drvs/util.cpp b/modules/core/src/common/vixen/hw/ata/drvs/util.cpp similarity index 89% rename from src/core/vixen/hw/ata/drvs/util.cpp rename to modules/core/src/common/vixen/hw/ata/drvs/util.cpp index ffe5790..b6e7b78 100644 --- a/src/core/vixen/hw/ata/drvs/util.cpp +++ b/modules/core/src/common/vixen/hw/ata/drvs/util.cpp @@ -1,4 +1,4 @@ -#include "util.h" +#include "vixen/hw/ata/drvs/util.h" namespace vixen { namespace hw { diff --git a/src/core/vixen/hw/atapi/atapi_common.cpp b/modules/core/src/common/vixen/hw/atapi/atapi_common.cpp similarity index 98% rename from src/core/vixen/hw/atapi/atapi_common.cpp rename to modules/core/src/common/vixen/hw/atapi/atapi_common.cpp index d6907e8..9c1fc74 100644 --- a/src/core/vixen/hw/atapi/atapi_common.cpp +++ b/modules/core/src/common/vixen/hw/atapi/atapi_common.cpp @@ -26,7 +26,7 @@ // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. References are prefixed by // the letter in brackets as listed above. -#include "atapi_common.h" +#include "vixen/hw/atapi/atapi_common.h" namespace vixen { namespace hw { diff --git a/src/core/vixen/hw/atapi/cmds/atapi_command.cpp b/modules/core/src/common/vixen/hw/atapi/cmds/atapi_command.cpp similarity index 96% rename from src/core/vixen/hw/atapi/cmds/atapi_command.cpp rename to modules/core/src/common/vixen/hw/atapi/cmds/atapi_command.cpp index 5c8e109..765406c 100644 --- a/src/core/vixen/hw/atapi/cmds/atapi_command.cpp +++ b/modules/core/src/common/vixen/hw/atapi/cmds/atapi_command.cpp @@ -26,7 +26,7 @@ // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. References are prefixed by // the letter in brackets as listed above. -#include "atapi_command.h" +#include "vixen/hw/atapi/cmds/atapi_command.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/atapi/cmds/cmd_mode_sense_10.cpp b/modules/core/src/common/vixen/hw/atapi/cmds/cmd_mode_sense_10.cpp similarity index 97% rename from src/core/vixen/hw/atapi/cmds/cmd_mode_sense_10.cpp rename to modules/core/src/common/vixen/hw/atapi/cmds/cmd_mode_sense_10.cpp index 51d974c..6baf52f 100644 --- a/src/core/vixen/hw/atapi/cmds/cmd_mode_sense_10.cpp +++ b/modules/core/src/common/vixen/hw/atapi/cmds/cmd_mode_sense_10.cpp @@ -26,7 +26,7 @@ // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. References are prefixed by // the letter in brackets as listed above. -#include "cmd_mode_sense_10.h" +#include "vixen/hw/atapi/cmds/cmd_mode_sense_10.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/atapi/cmds/cmd_read_10.cpp b/modules/core/src/common/vixen/hw/atapi/cmds/cmd_read_10.cpp similarity index 98% rename from src/core/vixen/hw/atapi/cmds/cmd_read_10.cpp rename to modules/core/src/common/vixen/hw/atapi/cmds/cmd_read_10.cpp index 537238a..eea1f06 100644 --- a/src/core/vixen/hw/atapi/cmds/cmd_read_10.cpp +++ b/modules/core/src/common/vixen/hw/atapi/cmds/cmd_read_10.cpp @@ -26,7 +26,7 @@ // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. References are prefixed by // the letter in brackets as listed above. -#include "cmd_read_10.h" +#include "vixen/hw/atapi/cmds/cmd_read_10.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/atapi/cmds/cmd_read_capacity.cpp b/modules/core/src/common/vixen/hw/atapi/cmds/cmd_read_capacity.cpp similarity index 97% rename from src/core/vixen/hw/atapi/cmds/cmd_read_capacity.cpp rename to modules/core/src/common/vixen/hw/atapi/cmds/cmd_read_capacity.cpp index 301326e..0dcaf9d 100644 --- a/src/core/vixen/hw/atapi/cmds/cmd_read_capacity.cpp +++ b/modules/core/src/common/vixen/hw/atapi/cmds/cmd_read_capacity.cpp @@ -26,7 +26,7 @@ // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. References are prefixed by // the letter in brackets as listed above. -#include "cmd_read_capacity.h" +#include "vixen/hw/atapi/cmds/cmd_read_capacity.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/atapi/cmds/cmd_read_dvd_structure.cpp b/modules/core/src/common/vixen/hw/atapi/cmds/cmd_read_dvd_structure.cpp similarity index 98% rename from src/core/vixen/hw/atapi/cmds/cmd_read_dvd_structure.cpp rename to modules/core/src/common/vixen/hw/atapi/cmds/cmd_read_dvd_structure.cpp index 393e180..43de076 100644 --- a/src/core/vixen/hw/atapi/cmds/cmd_read_dvd_structure.cpp +++ b/modules/core/src/common/vixen/hw/atapi/cmds/cmd_read_dvd_structure.cpp @@ -26,7 +26,7 @@ // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. References are prefixed by // the letter in brackets as listed above. -#include "cmd_read_dvd_structure.h" +#include "vixen/hw/atapi/cmds/cmd_read_dvd_structure.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/atapi/cmds/cmd_test_unit_ready.cpp b/modules/core/src/common/vixen/hw/atapi/cmds/cmd_test_unit_ready.cpp similarity index 97% rename from src/core/vixen/hw/atapi/cmds/cmd_test_unit_ready.cpp rename to modules/core/src/common/vixen/hw/atapi/cmds/cmd_test_unit_ready.cpp index a5890ae..a23c3da 100644 --- a/src/core/vixen/hw/atapi/cmds/cmd_test_unit_ready.cpp +++ b/modules/core/src/common/vixen/hw/atapi/cmds/cmd_test_unit_ready.cpp @@ -26,7 +26,7 @@ // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. References are prefixed by // the letter in brackets as listed above. -#include "cmd_test_unit_ready.h" +#include "vixen/hw/atapi/cmds/cmd_test_unit_ready.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/atapi/cmds/proto_data_in.cpp b/modules/core/src/common/vixen/hw/atapi/cmds/proto_data_in.cpp similarity index 97% rename from src/core/vixen/hw/atapi/cmds/proto_data_in.cpp rename to modules/core/src/common/vixen/hw/atapi/cmds/proto_data_in.cpp index fda6dc0..96e79e2 100644 --- a/src/core/vixen/hw/atapi/cmds/proto_data_in.cpp +++ b/modules/core/src/common/vixen/hw/atapi/cmds/proto_data_in.cpp @@ -26,7 +26,7 @@ // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. References are prefixed by // the letter in brackets as listed above. -#include "proto_data_in.h" +#include "vixen/hw/atapi/cmds/proto_data_in.h" #include "vixen/log.h" diff --git a/src/core/vixen/hw/atapi/cmds/proto_nondata.cpp b/modules/core/src/common/vixen/hw/atapi/cmds/proto_nondata.cpp similarity index 96% rename from src/core/vixen/hw/atapi/cmds/proto_nondata.cpp rename to modules/core/src/common/vixen/hw/atapi/cmds/proto_nondata.cpp index f4d662a..3b03aa1 100644 --- a/src/core/vixen/hw/atapi/cmds/proto_nondata.cpp +++ b/modules/core/src/common/vixen/hw/atapi/cmds/proto_nondata.cpp @@ -26,7 +26,7 @@ // References to particular items in the specification are denoted between brackets // optionally followed by a quote from the specification. References are prefixed by // the letter in brackets as listed above. -#include "proto_nondata.h" +#include "vixen/hw/atapi/cmds/proto_nondata.h" #include "vixen/log.h" diff --git a/modules/core/src/common/vixen/hw/basic/char.cpp b/modules/core/src/common/vixen/hw/basic/char.cpp new file mode 100644 index 0000000..9ec18d2 --- /dev/null +++ b/modules/core/src/common/vixen/hw/basic/char.cpp @@ -0,0 +1,7 @@ +#include "vixen/hw/basic/char.h" + +namespace vixen { + + + +} diff --git a/src/core/vixen/hw/basic/char_null.cpp b/modules/core/src/common/vixen/hw/basic/char_null.cpp similarity index 93% rename from src/core/vixen/hw/basic/char_null.cpp rename to modules/core/src/common/vixen/hw/basic/char_null.cpp index c73aad5..8ddd2dc 100644 --- a/src/core/vixen/hw/basic/char_null.cpp +++ b/modules/core/src/common/vixen/hw/basic/char_null.cpp @@ -1,4 +1,4 @@ -#include "char_null.h" +#include "vixen/hw/basic/char_null.h" namespace vixen { diff --git a/src/core/vixen/hw/basic/cmos.cpp b/modules/core/src/common/vixen/hw/basic/cmos.cpp similarity index 99% rename from src/core/vixen/hw/basic/cmos.cpp rename to modules/core/src/common/vixen/hw/basic/cmos.cpp index 10c874a..d04e195 100644 --- a/src/core/vixen/hw/basic/cmos.cpp +++ b/modules/core/src/common/vixen/hw/basic/cmos.cpp @@ -1,4 +1,4 @@ -#include "cmos.h" +#include "vixen/hw/basic/cmos.h" #include "vixen/log.h" #include "vixen/io.h" diff --git a/src/core/vixen/hw/basic/gsi.cpp b/modules/core/src/common/vixen/hw/basic/gsi.cpp similarity index 90% rename from src/core/vixen/hw/basic/gsi.cpp rename to modules/core/src/common/vixen/hw/basic/gsi.cpp index bea2b03..1cddbe2 100644 --- a/src/core/vixen/hw/basic/gsi.cpp +++ b/modules/core/src/common/vixen/hw/basic/gsi.cpp @@ -1,4 +1,4 @@ -#include "gsi.h" +#include "vixen/hw/basic/gsi.h" namespace vixen { diff --git a/src/core/vixen/hw/basic/i8254.cpp b/modules/core/src/common/vixen/hw/basic/i8254.cpp similarity index 98% rename from src/core/vixen/hw/basic/i8254.cpp rename to modules/core/src/common/vixen/hw/basic/i8254.cpp index b5d7593..13b5233 100644 --- a/src/core/vixen/hw/basic/i8254.cpp +++ b/modules/core/src/common/vixen/hw/basic/i8254.cpp @@ -25,9 +25,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "i8254.h" +#include "vixen/hw/basic/i8254.h" -#include +#include "vixen/thread.h" namespace vixen { diff --git a/src/core/vixen/hw/basic/i8259.cpp b/modules/core/src/common/vixen/hw/basic/i8259.cpp similarity index 98% rename from src/core/vixen/hw/basic/i8259.cpp rename to modules/core/src/common/vixen/hw/basic/i8259.cpp index 56ddea1..d230f86 100644 --- a/src/core/vixen/hw/basic/i8259.cpp +++ b/modules/core/src/common/vixen/hw/basic/i8259.cpp @@ -25,15 +25,13 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "i8259.h" +#include "vixen/hw/basic/i8259.h" #include "vixen/log.h" #include "vixen/io.h" namespace vixen { -using namespace vixen::cpu; - // Implementation based on QEMU: // https://github.com/qemu/qemu/blob/master/hw/intc/i8259_common.c // https://github.com/qemu/qemu/blob/master/hw/intc/i8259.c @@ -66,8 +64,8 @@ using namespace vixen::cpu; // TODO: Implement ELCR support -i8259::i8259(Cpu& cpu) - : m_cpu(cpu) +i8259::i8259(virt86::VirtualProcessor& vp) + : m_vp(vp) { } @@ -437,7 +435,7 @@ void i8259::UpdateIRQ(int pic) { // If this was the master PIC, trigger the IRQ if (pic == PIC_MASTER && m_InterruptOutput[PIC_MASTER]) { - m_cpu.Interrupt(GetCurrentIRQ()); + m_vp.EnqueueInterrupt(GetCurrentIRQ()); } } diff --git a/src/core/vixen/hw/basic/irq.cpp b/modules/core/src/common/vixen/hw/basic/irq.cpp similarity index 88% rename from src/core/vixen/hw/basic/irq.cpp rename to modules/core/src/common/vixen/hw/basic/irq.cpp index 38d1783..00b918e 100644 --- a/src/core/vixen/hw/basic/irq.cpp +++ b/modules/core/src/common/vixen/hw/basic/irq.cpp @@ -1,4 +1,4 @@ -#include "irq.h" +#include "vixen/hw/basic/irq.h" namespace vixen { diff --git a/src/core/vixen/hw/basic/mcpx.cpp b/modules/core/src/common/vixen/hw/basic/mcpx.cpp similarity index 89% rename from src/core/vixen/hw/basic/mcpx.cpp rename to modules/core/src/common/vixen/hw/basic/mcpx.cpp index 61cef20..4112a21 100644 --- a/src/core/vixen/hw/basic/mcpx.cpp +++ b/modules/core/src/common/vixen/hw/basic/mcpx.cpp @@ -1,5 +1,6 @@ -#include "../defs.h" -#include "mcpx.h" +#include "vixen/hw/basic/mcpx.h" + +#include "vixen/hw/defs.h" namespace vixen { diff --git a/src/core/vixen/hw/basic/serial.cpp b/modules/core/src/common/vixen/hw/basic/serial.cpp similarity index 99% rename from src/core/vixen/hw/basic/serial.cpp rename to modules/core/src/common/vixen/hw/basic/serial.cpp index f7d5c66..beedca5 100644 --- a/src/core/vixen/hw/basic/serial.cpp +++ b/modules/core/src/common/vixen/hw/basic/serial.cpp @@ -26,7 +26,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "serial.h" +#include "vixen/hw/basic/serial.h" #include "vixen/log.h" #include "vixen/io.h" diff --git a/src/core/vixen/hw/basic/superio.cpp b/modules/core/src/common/vixen/hw/basic/superio.cpp similarity index 99% rename from src/core/vixen/hw/basic/superio.cpp rename to modules/core/src/common/vixen/hw/basic/superio.cpp index e57e9f8..634b089 100644 --- a/src/core/vixen/hw/basic/superio.cpp +++ b/modules/core/src/common/vixen/hw/basic/superio.cpp @@ -20,7 +20,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ -#include "superio.h" +#include "vixen/hw/basic/superio.h" #include "vixen/log.h" #include "vixen/io.h" diff --git a/src/core/vixen/hw/bus/isabus.cpp b/modules/core/src/common/vixen/hw/bus/isabus.cpp similarity index 97% rename from src/core/vixen/hw/bus/isabus.cpp rename to modules/core/src/common/vixen/hw/bus/isabus.cpp index 7f3cc4c..8649d20 100644 --- a/src/core/vixen/hw/bus/isabus.cpp +++ b/modules/core/src/common/vixen/hw/bus/isabus.cpp @@ -20,7 +20,8 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ -#include "isabus.h" +#include "vixen/hw/bus/isabus.h" + #include "vixen/log.h" namespace vixen { diff --git a/src/core/vixen/hw/bus/pcibus.cpp b/modules/core/src/common/vixen/hw/bus/pcibus.cpp similarity index 99% rename from src/core/vixen/hw/bus/pcibus.cpp rename to modules/core/src/common/vixen/hw/bus/pcibus.cpp index e5f0c7c..e29df14 100644 --- a/src/core/vixen/hw/bus/pcibus.cpp +++ b/modules/core/src/common/vixen/hw/bus/pcibus.cpp @@ -25,7 +25,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "pcibus.h" +#include "vixen/hw/bus/pcibus.h" + #include "vixen/log.h" #include diff --git a/src/core/vixen/hw/bus/smbus.cpp b/modules/core/src/common/vixen/hw/bus/smbus.cpp similarity index 99% rename from src/core/vixen/hw/bus/smbus.cpp rename to modules/core/src/common/vixen/hw/bus/smbus.cpp index 39c91b5..c09d26b 100644 --- a/src/core/vixen/hw/bus/smbus.cpp +++ b/modules/core/src/common/vixen/hw/bus/smbus.cpp @@ -25,7 +25,8 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ -#include "smbus.h" +#include "vixen/hw/bus/smbus.h" + #include "vixen/log.h" namespace vixen { diff --git a/src/core/vixen/hw/ohci/ohci.cpp b/modules/core/src/common/vixen/hw/ohci/ohci.cpp similarity index 99% rename from src/core/vixen/hw/ohci/ohci.cpp rename to modules/core/src/common/vixen/hw/ohci/ohci.cpp index 53fa8c6..01d8874 100644 --- a/src/core/vixen/hw/ohci/ohci.cpp +++ b/modules/core/src/common/vixen/hw/ohci/ohci.cpp @@ -34,7 +34,8 @@ // * // ****************************************************************** -#include "ohci.h" +#include "vixen/hw/ohci/ohci.h" + #include "vixen/log.h" #include @@ -44,7 +45,11 @@ namespace vixen { -using namespace vixen::cpu; +#define ONE_KB 1024 +#define ONE_MB (1024 * 1024) + +#define XBOX_MEMORY_SIZE (64 * ONE_MB) +#define CONTIGUOUS_MEMORY_BASE 0x80000000 // Compute (a*b)/c with a 96 bit intermediate result static inline uint64_t Muldiv64(uint64_t a, uint32_t b, uint32_t c) { @@ -214,8 +219,8 @@ static inline uint64_t Muldiv64(uint64_t a, uint32_t b, uint32_t c) { #define OHCI_PAGE_MASK 0xFFFFF000 #define OHCI_OFFSET_MASK 0xFFF -OHCI::OHCI(Cpu& cpu, int Irq, USBPCIDevice* UsbObj) - : m_cpu(cpu) +OHCI::OHCI(virt86::VirtualProcessor& vp, int Irq, USBPCIDevice* UsbObj) + : m_vp(vp) { int offset = 0; USBPortOps* ops; @@ -387,7 +392,7 @@ bool OHCI::OHCI_WriteHCCA(uint32_t Paddr, OHCI_HCCA* Hcca) bool OHCI::OHCI_ReadED(uint32_t Paddr, OHCI_ED* Ed) { if (Paddr != 0) { - m_cpu.VMemRead(Paddr, sizeof(*Ed), Ed); + m_vp.LMemRead(Paddr, sizeof(*Ed), Ed); return false; } return true; // error @@ -398,7 +403,7 @@ bool OHCI::OHCI_WriteED(uint32_t Paddr, OHCI_ED* Ed) if (Paddr != 0) { // According to the standard, only the HeadP field is writable by the HC, so we'll write just that size_t OffsetOfHeadP = offsetof(OHCI_ED, HeadP); - m_cpu.VMemWrite(Paddr, 4, Ed + OffsetOfHeadP); + m_vp.LMemWrite(Paddr, 4, Ed + OffsetOfHeadP); return false; } return true; // error @@ -407,7 +412,7 @@ bool OHCI::OHCI_WriteED(uint32_t Paddr, OHCI_ED* Ed) bool OHCI::OHCI_ReadTD(uint32_t Paddr, OHCI_TD* Td) { if (Paddr != 0) { - m_cpu.VMemRead(Paddr, sizeof(*Td), Td); + m_vp.LMemRead(Paddr, sizeof(*Td), Td); return false; } return true; // error @@ -416,7 +421,7 @@ bool OHCI::OHCI_ReadTD(uint32_t Paddr, OHCI_TD* Td) bool OHCI::OHCI_WriteTD(uint32_t Paddr, OHCI_TD* Td) { if (Paddr != 0) { - m_cpu.VMemWrite(Paddr, sizeof(*Td), Td); + m_vp.LMemWrite(Paddr, sizeof(*Td), Td); return false; } return true; // error @@ -424,7 +429,7 @@ bool OHCI::OHCI_WriteTD(uint32_t Paddr, OHCI_TD* Td) bool OHCI::OHCI_ReadIsoTD(uint32_t Paddr, OHCI_ISO_TD* td) { if (Paddr != 0) { - m_cpu.VMemRead(Paddr, sizeof(*td), td); + m_vp.LMemRead(Paddr, sizeof(*td), td); return false; } return true; // error @@ -432,7 +437,7 @@ bool OHCI::OHCI_ReadIsoTD(uint32_t Paddr, OHCI_ISO_TD* td) { bool OHCI::OHCI_WriteIsoTD(uint32_t Paddr, OHCI_ISO_TD* td) { if (Paddr != 0) { - m_cpu.VMemWrite(Paddr, sizeof(*td), td); + m_vp.LMemWrite(Paddr, sizeof(*td), td); return false; } return true; // error diff --git a/src/core/vixen/hw/ohci/ohci_hub.cpp b/modules/core/src/common/vixen/hw/ohci/ohci_hub.cpp similarity index 99% rename from src/core/vixen/hw/ohci/ohci_hub.cpp rename to modules/core/src/common/vixen/hw/ohci/ohci_hub.cpp index 889022b..6dd76f0 100644 --- a/src/core/vixen/hw/ohci/ohci_hub.cpp +++ b/modules/core/src/common/vixen/hw/ohci/ohci_hub.cpp @@ -40,10 +40,10 @@ #include -#include "vixen/log.h" +#include "vixen/hw/ohci/ohci.h" +#include "vixen/hw/ohci/ohci_hub.h" -#include "ohci.h" -#include "ohci_hub.h" +#include "vixen/log.h" namespace vixen { diff --git a/src/core/vixen/hw/pci/ac97.cpp b/modules/core/src/common/vixen/hw/pci/ac97.cpp similarity index 98% rename from src/core/vixen/hw/pci/ac97.cpp rename to modules/core/src/common/vixen/hw/pci/ac97.cpp index 2d6a713..ebc200e 100644 --- a/src/core/vixen/hw/pci/ac97.cpp +++ b/modules/core/src/common/vixen/hw/pci/ac97.cpp @@ -1,4 +1,5 @@ -#include "ac97.h" +#include "vixen/hw/pci/ac97.h" + #include "vixen/log.h" namespace vixen { diff --git a/src/core/vixen/hw/pci/agpbridge.cpp b/modules/core/src/common/vixen/hw/pci/agpbridge.cpp similarity index 97% rename from src/core/vixen/hw/pci/agpbridge.cpp rename to modules/core/src/common/vixen/hw/pci/agpbridge.cpp index 0571ca1..8d88d2d 100644 --- a/src/core/vixen/hw/pci/agpbridge.cpp +++ b/modules/core/src/common/vixen/hw/pci/agpbridge.cpp @@ -1,4 +1,5 @@ -#include "agpbridge.h" +#include "vixen/hw/pci/agpbridge.h" + #include "vixen/log.h" namespace vixen { diff --git a/src/core/vixen/hw/pci/bmide.cpp b/modules/core/src/common/vixen/hw/pci/bmide.cpp similarity index 99% rename from src/core/vixen/hw/pci/bmide.cpp rename to modules/core/src/common/vixen/hw/pci/bmide.cpp index 33567eb..d2920f7 100644 --- a/src/core/vixen/hw/pci/bmide.cpp +++ b/modules/core/src/common/vixen/hw/pci/bmide.cpp @@ -5,7 +5,8 @@ // Revision 1.0 available at http://www.bswd.com/idems100.pdf // and complemented with information from PC87415 at // https://parisc.wiki.kernel.org/images-parisc/0/0a/PC87415.pdf -#include "bmide.h" +#include "vixen/hw/pci/bmide.h" + #include "vixen/log.h" #include "vixen/thread.h" diff --git a/src/core/vixen/hw/pci/bmide_channel.cpp b/modules/core/src/common/vixen/hw/pci/bmide_channel.cpp similarity index 99% rename from src/core/vixen/hw/pci/bmide_channel.cpp rename to modules/core/src/common/vixen/hw/pci/bmide_channel.cpp index 7afad47..336a620 100644 --- a/src/core/vixen/hw/pci/bmide_channel.cpp +++ b/modules/core/src/common/vixen/hw/pci/bmide_channel.cpp @@ -5,7 +5,8 @@ // Revision 1.0 available at http://www.bswd.com/idems100.pdf // and complemented with information from PC87415 at // https://parisc.wiki.kernel.org/images-parisc/0/0a/PC87415.pdf -#include "bmide.h" +#include "vixen/hw/pci/bmide.h" + #include "vixen/log.h" #include "vixen/thread.h" diff --git a/src/core/vixen/hw/pci/hostbridge.cpp b/modules/core/src/common/vixen/hw/pci/hostbridge.cpp similarity index 98% rename from src/core/vixen/hw/pci/hostbridge.cpp rename to modules/core/src/common/vixen/hw/pci/hostbridge.cpp index a872ea9..42cf33c 100644 --- a/src/core/vixen/hw/pci/hostbridge.cpp +++ b/modules/core/src/common/vixen/hw/pci/hostbridge.cpp @@ -1,4 +1,5 @@ -#include "hostbridge.h" +#include "vixen/hw/pci/hostbridge.h" + #include "vixen/log.h" namespace vixen { diff --git a/src/core/vixen/hw/pci/lpc.cpp b/modules/core/src/common/vixen/hw/pci/lpc.cpp similarity index 98% rename from src/core/vixen/hw/pci/lpc.cpp rename to modules/core/src/common/vixen/hw/pci/lpc.cpp index 57444d6..88b2979 100644 --- a/src/core/vixen/hw/pci/lpc.cpp +++ b/modules/core/src/common/vixen/hw/pci/lpc.cpp @@ -20,7 +20,8 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ -#include "lpc.h" +#include "vixen/hw/pci/lpc.h" + #include "vixen/log.h" #include "vixen/mem.h" @@ -103,7 +104,7 @@ void LPCDevice::Reset() { memcpy(m_rom, m_bios, m_biosSize); // Replicate BIOS ROM image across the entire 16 MiB range - for (uint32_t addr = m_biosSize; addr < MiB(16); addr += m_biosSize) { + for (uint32_t addr = m_biosSize; addr < (16 * MiB); addr += m_biosSize) { memcpy(m_rom + addr, m_rom, m_biosSize); } diff --git a/src/core/vixen/hw/pci/mcpx_ram.cpp b/modules/core/src/common/vixen/hw/pci/mcpx_ram.cpp similarity index 94% rename from src/core/vixen/hw/pci/mcpx_ram.cpp rename to modules/core/src/common/vixen/hw/pci/mcpx_ram.cpp index e677eb9..0541b2b 100644 --- a/src/core/vixen/hw/pci/mcpx_ram.cpp +++ b/modules/core/src/common/vixen/hw/pci/mcpx_ram.cpp @@ -1,4 +1,5 @@ -#include "mcpx_ram.h" +#include "vixen/hw/pci/mcpx_ram.h" + #include "vixen/log.h" namespace vixen { diff --git a/src/core/vixen/hw/pci/nv2a.cpp b/modules/core/src/common/vixen/hw/pci/nv2a.cpp similarity index 99% rename from src/core/vixen/hw/pci/nv2a.cpp rename to modules/core/src/common/vixen/hw/pci/nv2a.cpp index d525a39..5f3d5cb 100644 --- a/src/core/vixen/hw/pci/nv2a.cpp +++ b/modules/core/src/common/vixen/hw/pci/nv2a.cpp @@ -23,7 +23,8 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ -#include "nv2a.h" +#include "vixen/hw/pci/nv2a.h" + #include "vixen/log.h" #include "vixen/thread.h" diff --git a/src/core/vixen/hw/pci/nvapu.cpp b/modules/core/src/common/vixen/hw/pci/nvapu.cpp similarity index 99% rename from src/core/vixen/hw/pci/nvapu.cpp rename to modules/core/src/common/vixen/hw/pci/nvapu.cpp index 30185ae..d192438 100644 --- a/src/core/vixen/hw/pci/nvapu.cpp +++ b/modules/core/src/common/vixen/hw/pci/nvapu.cpp @@ -38,7 +38,8 @@ // * // ****************************************************************** -#include "nvapu.h" +#include "vixen/hw/pci/nvapu.h" + #include "vixen/log.h" namespace vixen { diff --git a/src/core/vixen/hw/pci/nvnet.cpp b/modules/core/src/common/vixen/hw/pci/nvnet.cpp similarity index 99% rename from src/core/vixen/hw/pci/nvnet.cpp rename to modules/core/src/common/vixen/hw/pci/nvnet.cpp index 01ff6d3..a7673df 100644 --- a/src/core/vixen/hw/pci/nvnet.cpp +++ b/modules/core/src/common/vixen/hw/pci/nvnet.cpp @@ -21,7 +21,8 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ -#include "nvnet.h" +#include "vixen/hw/pci/nvnet.h" + #include "vixen/log.h" namespace vixen { diff --git a/src/core/vixen/hw/pci/pci.cpp b/modules/core/src/common/vixen/hw/pci/pci.cpp similarity index 99% rename from src/core/vixen/hw/pci/pci.cpp rename to modules/core/src/common/vixen/hw/pci/pci.cpp index 9dc65a2..67e9435 100644 --- a/src/core/vixen/hw/pci/pci.cpp +++ b/modules/core/src/common/vixen/hw/pci/pci.cpp @@ -25,8 +25,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "pci.h" -#include "../bus/pcibus.h" +#include "vixen/hw/pci/pci.h" + +#include "vixen/hw/bus/pcibus.h" #include "vixen/log.h" #include diff --git a/src/core/vixen/hw/pci/pci_irq.cpp b/modules/core/src/common/vixen/hw/pci/pci_irq.cpp similarity index 89% rename from src/core/vixen/hw/pci/pci_irq.cpp rename to modules/core/src/common/vixen/hw/pci/pci_irq.cpp index f20844b..f17366d 100644 --- a/src/core/vixen/hw/pci/pci_irq.cpp +++ b/modules/core/src/common/vixen/hw/pci/pci_irq.cpp @@ -1,4 +1,4 @@ -#include "pci_irq.h" +#include "vixen/hw/pci/pci_irq.h" namespace vixen { diff --git a/src/core/vixen/hw/pci/pcibridge.cpp b/modules/core/src/common/vixen/hw/pci/pcibridge.cpp similarity index 98% rename from src/core/vixen/hw/pci/pcibridge.cpp rename to modules/core/src/common/vixen/hw/pci/pcibridge.cpp index 2de6793..643d7c2 100644 --- a/src/core/vixen/hw/pci/pcibridge.cpp +++ b/modules/core/src/common/vixen/hw/pci/pcibridge.cpp @@ -32,9 +32,10 @@ * Copyright (c) 2010 Isaku Yamahata * VA Linux Systems Japan K.K. */ -#include "pcibridge.h" +#include "vixen/hw/pci/pcibridge.h" + #include "vixen/log.h" -#include "../utils.h" +#include "vixen/hw/utils.h" namespace vixen { diff --git a/src/core/vixen/hw/pci/usb_pci.cpp b/modules/core/src/common/vixen/hw/pci/usb_pci.cpp similarity index 99% rename from src/core/vixen/hw/pci/usb_pci.cpp rename to modules/core/src/common/vixen/hw/pci/usb_pci.cpp index 17fa34e..dafeb5a 100644 --- a/src/core/vixen/hw/pci/usb_pci.cpp +++ b/modules/core/src/common/vixen/hw/pci/usb_pci.cpp @@ -44,24 +44,22 @@ #include "vixen/log.h" -#include "usb_pci.h" -#include "../ohci/ohci.h" +#include "vixen/hw/pci/usb_pci.h" +#include "vixen/hw/ohci/ohci.h" namespace vixen { -using namespace vixen::cpu; - #define SETUP_STATE_IDLE 0 #define SETUP_STATE_SETUP 1 #define SETUP_STATE_DATA 2 #define SETUP_STATE_ACK 3 #define SETUP_STATE_PARAM 4 -USBPCIDevice::USBPCIDevice(uint8_t irqn, Cpu& cpu) +USBPCIDevice::USBPCIDevice(uint8_t irqn, virt86::VirtualProcessor& vp) : PCIDevice(PCI_HEADER_TYPE_NORMAL, PCI_VENDOR_ID_NVIDIA, 0x01C2, 0xB1, 0x0c, 0x03, 0x10) // USB OHCI , m_irqn(irqn) - , m_cpu(cpu) + , m_vp(vp) { } @@ -94,7 +92,7 @@ void USBPCIDevice::Init() { m_PciPath = "pci.0:03.0"; } - m_HostController = new OHCI(m_cpu, m_irqn, this); + m_HostController = new OHCI(m_vp, m_irqn, this); } void USBPCIDevice::Reset() { diff --git a/src/core/vixen/hw/sm/adm1032.cpp b/modules/core/src/common/vixen/hw/sm/adm1032.cpp similarity index 96% rename from src/core/vixen/hw/sm/adm1032.cpp rename to modules/core/src/common/vixen/hw/sm/adm1032.cpp index b83c1d2..6203637 100644 --- a/src/core/vixen/hw/sm/adm1032.cpp +++ b/modules/core/src/common/vixen/hw/sm/adm1032.cpp @@ -1,7 +1,7 @@ // (C) Ivan "StrikerX3" Oliveira // // Datasheet: https://www.onsemi.com/pub/Collateral/ADM1032-D.PDF -#include "adm1032.h" +#include "vixen/hw/sm/adm1032.h" namespace vixen { diff --git a/src/core/vixen/hw/sm/eeprom.cpp b/modules/core/src/common/vixen/hw/sm/eeprom.cpp similarity index 96% rename from src/core/vixen/hw/sm/eeprom.cpp rename to modules/core/src/common/vixen/hw/sm/eeprom.cpp index 410f7d3..38760ec 100644 --- a/src/core/vixen/hw/sm/eeprom.cpp +++ b/modules/core/src/common/vixen/hw/sm/eeprom.cpp @@ -1,4 +1,4 @@ -#include "eeprom.h" +#include "vixen/hw/sm/eeprom.h" #include diff --git a/modules/core/src/common/vixen/hw/sm/sm.cpp b/modules/core/src/common/vixen/hw/sm/sm.cpp new file mode 100644 index 0000000..127baf1 --- /dev/null +++ b/modules/core/src/common/vixen/hw/sm/sm.cpp @@ -0,0 +1,7 @@ +#include "vixen/hw/sm/sm.h" + +namespace vixen { + + + +} diff --git a/src/core/vixen/hw/sm/smc.cpp b/modules/core/src/common/vixen/hw/sm/smc.cpp similarity index 99% rename from src/core/vixen/hw/sm/smc.cpp rename to modules/core/src/common/vixen/hw/sm/smc.cpp index 6b0811d..623f93f 100644 --- a/src/core/vixen/hw/sm/smc.cpp +++ b/modules/core/src/common/vixen/hw/sm/smc.cpp @@ -20,8 +20,9 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ -#include "smc.h" -#include "led.h" +#include "vixen/hw/sm/smc.h" +#include "vixen/hw/sm/led.h" + #include "vixen/log.h" namespace vixen { diff --git a/src/core/vixen/hw/sm/tvenc.cpp b/modules/core/src/common/vixen/hw/sm/tvenc.cpp similarity index 96% rename from src/core/vixen/hw/sm/tvenc.cpp rename to modules/core/src/common/vixen/hw/sm/tvenc.cpp index 433f934..fc904cb 100644 --- a/src/core/vixen/hw/sm/tvenc.cpp +++ b/modules/core/src/common/vixen/hw/sm/tvenc.cpp @@ -1,4 +1,4 @@ -#include "tvenc.h" +#include "vixen/hw/sm/tvenc.h" namespace vixen { diff --git a/src/core/vixen/hw/sm/tvenc_conexant.cpp b/modules/core/src/common/vixen/hw/sm/tvenc_conexant.cpp similarity index 96% rename from src/core/vixen/hw/sm/tvenc_conexant.cpp rename to modules/core/src/common/vixen/hw/sm/tvenc_conexant.cpp index 85ac4fd..5b45ab6 100644 --- a/src/core/vixen/hw/sm/tvenc_conexant.cpp +++ b/modules/core/src/common/vixen/hw/sm/tvenc_conexant.cpp @@ -1,4 +1,4 @@ -#include "tvenc_conexant.h" +#include "vixen/hw/sm/tvenc_conexant.h" namespace vixen { diff --git a/src/core/vixen/hw/xid/xid_gamepad.cpp b/modules/core/src/common/vixen/hw/xid/xid_gamepad.cpp similarity index 99% rename from src/core/vixen/hw/xid/xid_gamepad.cpp rename to modules/core/src/common/vixen/hw/xid/xid_gamepad.cpp index 04e3697..1f9f004 100644 --- a/src/core/vixen/hw/xid/xid_gamepad.cpp +++ b/modules/core/src/common/vixen/hw/xid/xid_gamepad.cpp @@ -38,9 +38,10 @@ // * // ****************************************************************** -#include "xid_gamepad.h" -#include "../ohci/ohci.h" -#include "../pci/usb_pci.h" +#include "vixen/hw/xid/xid_gamepad.h" + +#include "vixen/hw/ohci/ohci.h" +#include "vixen/hw/pci/usb_pci.h" #include diff --git a/src/common/vixen/io.cpp b/modules/core/src/common/vixen/io.cpp similarity index 99% rename from src/common/vixen/io.cpp rename to modules/core/src/common/vixen/io.cpp index 080cf14..e29d622 100644 --- a/src/common/vixen/io.cpp +++ b/modules/core/src/common/vixen/io.cpp @@ -1,4 +1,4 @@ -#include "io.h" +#include "vixen/io.h" #include "vixen/log.h" namespace vixen { diff --git a/src/common/vixen/iovec.cpp b/modules/core/src/common/vixen/iovec.cpp similarity index 99% rename from src/common/vixen/iovec.cpp rename to modules/core/src/common/vixen/iovec.cpp index b6c57ba..a9330bc 100644 --- a/src/common/vixen/iovec.cpp +++ b/modules/core/src/common/vixen/iovec.cpp @@ -35,7 +35,7 @@ // * All rights reserved // * // ****************************************************************** -#include "iovec.h" +#include "vixen/iovec.h" #include #include diff --git a/src/common/vixen/log.cpp b/modules/core/src/common/vixen/log.cpp similarity index 92% rename from src/common/vixen/log.cpp rename to modules/core/src/common/vixen/log.cpp index 1ffe84a..3f0546b 100644 --- a/src/common/vixen/log.cpp +++ b/modules/core/src/common/vixen/log.cpp @@ -1,5 +1,6 @@ +#include "vixen/log.h" + #include -#include "log.h" namespace vixen { diff --git a/src/core/vixen/timer.cpp b/modules/core/src/common/vixen/timer.cpp similarity index 94% rename from src/core/vixen/timer.cpp rename to modules/core/src/common/vixen/timer.cpp index 911d8ca..84cc6c6 100644 --- a/src/core/vixen/timer.cpp +++ b/modules/core/src/common/vixen/timer.cpp @@ -1,4 +1,5 @@ -#include "timer.h" +#include "vixen/timer.h" + #include namespace vixen { diff --git a/modules/core/src/common/vixen/util/fifo.cpp b/modules/core/src/common/vixen/util/fifo.cpp new file mode 100644 index 0000000..f9feb8a --- /dev/null +++ b/modules/core/src/common/vixen/util/fifo.cpp @@ -0,0 +1,7 @@ +#include "vixen/util/fifo.h" + +namespace vixen { + + + +} diff --git a/src/core/vixen/util/invoke_later.cpp b/modules/core/src/common/vixen/util/invoke_later.cpp similarity index 97% rename from src/core/vixen/util/invoke_later.cpp rename to modules/core/src/common/vixen/util/invoke_later.cpp index 2f2b64b..7a5394b 100644 --- a/src/core/vixen/util/invoke_later.cpp +++ b/modules/core/src/common/vixen/util/invoke_later.cpp @@ -1,4 +1,4 @@ -#include "invoke_later.h" +#include "vixen/util/invoke_later.h" #include diff --git a/src/core/vixen/xbox.cpp b/modules/core/src/common/vixen/xbox.cpp similarity index 80% rename from src/core/vixen/xbox.cpp rename to modules/core/src/common/vixen/xbox.cpp index 0d9e137..d68464c 100644 --- a/src/core/vixen/xbox.cpp +++ b/modules/core/src/common/vixen/xbox.cpp @@ -23,12 +23,14 @@ #include #endif -#include "Zydis/Zydis.h" +//#include "Zydis/Zydis.h" #include namespace vixen { +using namespace virt86; + // bunnie's EEPROM (1.0) const static uint8_t kDefaultEEPROM[] = { 0xe3, 0x1c, 0x5c, 0x23, 0x6a, 0x58, 0x68, 0x37, @@ -105,8 +107,8 @@ const static uint8_t kDefaultEEPROM[] = { /*! * Constructor */ -Xbox::Xbox(vixen::modules::cpu::ICPUModule *cpuModule) - : m_cpuModule(cpuModule) +Xbox::Xbox(Platform& platform) + : m_virt86Platform(platform) { } @@ -114,7 +116,7 @@ Xbox::Xbox(vixen::modules::cpu::ICPUModule *cpuModule) * Destructor */ Xbox::~Xbox() { - if (m_cpu) m_cpuModule->FreeCPU(m_cpu); + if (m_vm) m_virt86Platform.FreeVM(m_vm->get()); if (m_ram) { #ifdef _WIN32 vfree(m_ram); @@ -133,7 +135,6 @@ Xbox::~Xbox() { } if (m_bios != nullptr) delete[] m_bios; if (m_mcpxROM != nullptr) delete[] m_mcpxROM; - if (m_memRegion) delete m_memRegion; if (m_SMC != nullptr) delete m_SMC; if (m_EEPROM != nullptr) delete m_EEPROM; @@ -224,8 +225,8 @@ EmulatorStatus Xbox::Initialize() { EmulatorStatus result; result = InitFixupSettings(); if (result != EMUS_OK) return result; + result = InitVM(); if (result != EMUS_OK) return result; result = InitMemory(); if (result != EMUS_OK) return result; - result = InitCPU(); if (result != EMUS_OK) return result; result = InitHardware(); if (result != EMUS_OK) return result; result = InitDebugger(); if (result != EMUS_OK) return result; @@ -243,13 +244,18 @@ EmulatorStatus Xbox::InitFixupSettings() { return EMUS_OK; } -EmulatorStatus Xbox::InitMemory() { - // Initialize 4 GiB address space - m_memRegion = new MemoryRegion(MEM_REGION_NONE, 0x00000000, 0x100000000ULL, NULL); - if (m_memRegion == nullptr) { - return EMUS_INIT_ALLOC_MEM_RGN_FAILED; +EmulatorStatus Xbox::InitVM() { + VMSpecifications specs = { 0 }; + specs.numProcessors = 1; + m_vm = m_virt86Platform.CreateVM(specs); + if (!m_vm) { + return EMUS_INIT_VM_INIT_FAILED; } + return EMUS_OK; +} + +EmulatorStatus Xbox::InitMemory() { EmulatorStatus result; result = InitRAM(); if (result != EMUS_OK) return result; result = InitROM(); if (result != EMUS_OK) return result; @@ -277,11 +283,10 @@ EmulatorStatus Xbox::InitRAM() { memset(m_ram, 0, m_ramSize); // Map RAM at address 0x00000000 - MemoryRegion *rgn = new MemoryRegion(MEM_REGION_RAM, 0x00000000, m_ramSize, m_ram); - if (rgn == nullptr) { + auto result = m_vm->get().MapGuestMemory(0x00000000, m_ramSize, MemoryFlags::Read | MemoryFlags::Write | MemoryFlags::Execute, m_ram); + if (result != MemoryMappingStatus::OK) { return EMUS_INIT_ALLOC_RAM_RGN_FAILED; } - m_memRegion->AddSubRegion(rgn); return EMUS_OK; } @@ -305,11 +310,10 @@ EmulatorStatus Xbox::InitROM() { memset(m_rom, 0, XBOX_ROM_AREA_SIZE); // Map ROM to address 0xFF000000 - MemoryRegion *rgn = new MemoryRegion(MEM_REGION_ROM, 0xFF000000, XBOX_ROM_AREA_SIZE, m_rom); - if (rgn == nullptr) { + auto result = m_vm->get().MapGuestMemory(0xFF000000, XBOX_ROM_AREA_SIZE, MemoryFlags::Read | MemoryFlags::Execute, m_rom); + if (result != MemoryMappingStatus::OK) { return EMUS_INIT_ALLOC_ROM_RGN_FAILED; } - m_memRegion->AddSubRegion(rgn); // Load ROM files FILE *fp; @@ -344,7 +348,7 @@ EmulatorStatus Xbox::InitROM() { fseek(fp, 0, SEEK_END); sz = ftell(fp); fseek(fp, 0, SEEK_SET); - if (sz != KiB(256) && sz != MiB(1)) { + if (sz != (256*KiB) && sz != (1*MiB)) { log_debug("incorrect file size: %d (must be 256 KiB or 1024 KiB)\n", sz); return EMUS_INIT_BIOS_ROM_INVALID_SIZE; } @@ -358,31 +362,6 @@ EmulatorStatus Xbox::InitROM() { return EMUS_OK; } -EmulatorStatus Xbox::InitCPU() { - log_debug("Initializing CPU\n"); - if (m_cpuModule == nullptr) { - log_fatal("No CPU module specified\n"); - return EMUS_INIT_NO_CPU_MODULE; - } - m_cpu = m_cpuModule->GetCPU(); - if (m_cpu == nullptr) { - log_fatal("CPU instantiation failed\n"); - return EMUS_INIT_CPU_CREATE_FAILED; - } - if (m_cpu->Initialize(&m_ioMapper)) { - log_fatal("CPU initialization failed\n"); - return EMUS_INIT_CPU_INIT_FAILED; - } - - // Allow CPU to update memory map - auto result = m_cpu->MemMap(m_memRegion); - if (result != CPUS_MMAP_OK) { - return EMUS_INIT_CPU_MEM_MAP_FAILED; - } - - return EMUS_OK; -} - EmulatorStatus Xbox::InitHardware() { // Determine which revisions of which components should be used for the // specified hardware model @@ -392,12 +371,14 @@ EmulatorStatus Xbox::InitHardware() { log_debug("Initializing devices\n"); + auto& vp = m_vm->get().GetVirtualProcessor(0)->get(); + // Create IRQs m_GSI = new GSI(); m_IRQs = AllocateIRQs(m_GSI, GSI_NUM_PINS); // Create basic system devices - m_i8259 = new i8259(*m_cpu); + m_i8259 = new i8259(vp); m_i8254 = new i8254(*m_i8259, m_settings.hw_sysclock_tickRate); m_CMOS = new CMOS(); @@ -494,8 +475,8 @@ EmulatorStatus Xbox::InitHardware() { m_HostBridge = new HostBridgeDevice(); m_MCPXRAM = new MCPXRAMDevice(mcpxRevision); m_LPC = new LPCDevice(m_IRQs, m_rom, m_bios, m_biosSize, m_mcpxROM, m_settings.hw_revision != DebugKit); - m_USB1 = new USBPCIDevice(1, *m_cpu); - m_USB2 = new USBPCIDevice(9, *m_cpu); + m_USB1 = new USBPCIDevice(1, vp); + m_USB2 = new USBPCIDevice(9, vp); m_NVNet = new NVNetDevice(); m_NVAPU = new NVAPUDevice(); m_AC97 = new AC97Device(); @@ -577,13 +558,21 @@ EmulatorStatus Xbox::InitHardware() { // TODO: user-specified EEPROM m_EEPROM->SetEEPROM(kDefaultEEPROM); + // Register I/O callbacks and context + auto& vm = m_vm->get(); + vm.RegisterIOReadCallback(IOReadCallback); + vm.RegisterIOWriteCallback(IOWriteCallback); + vm.RegisterMMIOReadCallback(MMIOReadCallback); + vm.RegisterMMIOWriteCallback(MMIOWriteCallback); + vm.RegisterIOContext(this); + return EMUS_OK; } EmulatorStatus Xbox::InitDebugger() { // GDB Server if (m_settings.gdb_enable) { - m_gdb = new GdbServer(m_cpu, "127.0.0.1", 9269); + m_gdb = new GdbServer(m_vm->get().GetVirtualProcessor(0)->get(), "127.0.0.1", 9269); // TODO: handle result properly int result = m_gdb->Initialize(); if (result) { @@ -601,21 +590,61 @@ EmulatorStatus Xbox::InitDebugger() { bps.bp[0].address = 0x80016756; bps.bp[0].length = HWBP_LENGTH_1_BYTE; bps.bp[0].trigger = HWBP_TRIGGER_EXECUTION; - m_cpu->SetHardwareBreakpoints(bps);*/ + vp.SetHardwareBreakpoints(bps);*/ return EMUS_OK; } +uint32_t Xbox::IOReadCallback(void *context, uint16_t port, size_t size) { + Xbox *xbox = (Xbox *)context; + return xbox->IORead(port, size); +} + +void Xbox::IOWriteCallback(void *context, uint16_t port, size_t size, uint32_t value) { + Xbox *xbox = (Xbox *)context; + xbox->IOWrite(port, size, value); +} + +uint64_t Xbox::MMIOReadCallback(void *context, uint64_t address, size_t size) { + Xbox *xbox = (Xbox *)context; + return xbox->MMIORead(address, size); +} + +void Xbox::MMIOWriteCallback(void *context, uint64_t address, size_t size, uint64_t value) { + Xbox *xbox = (Xbox *)context; + xbox->MMIOWrite(address, size, value); +} + +uint32_t Xbox::IORead(uint16_t port, size_t size) { + uint32_t value = 0; + m_ioMapper.IORead(port, &value, size); + return value; +} + +void Xbox::IOWrite(uint16_t port, size_t size, uint32_t value) { + m_ioMapper.IOWrite(port, value, size); +} + +uint64_t Xbox::MMIORead(uint64_t address, size_t size) { + uint32_t value = 0; + m_ioMapper.IORead(address, &value, size); + return value; +} + +void Xbox::MMIOWrite(uint64_t address, size_t size, uint64_t value) { + m_ioMapper.MMIOWrite(address, value, size); +} + /*! * Advances the CPU emulation state. */ -int Xbox::RunCpu() -{ +int Xbox::RunCpu() { + auto& vp = m_vm->get().GetVirtualProcessor(0)->get(); + #if defined(_DEBUG) && 0 Timer t; #endif - int result; - struct CpuExitInfo *exit_info; + VPExecutionStatus result; if (!m_should_run) { return -1; @@ -627,10 +656,10 @@ int Xbox::RunCpu() t.Start(); #endif if (m_settings.cpu_singleStep) { - result = m_cpu->Step(); + result = vp.Step(); } else { - result = m_cpu->Run(); + result = vp.Run(); } #if defined(_DEBUG) && 0 t.Stop(); @@ -639,21 +668,19 @@ int Xbox::RunCpu() #if defined(_DEBUG) && 0 // Print CPU registers - uint32_t eip; - m_cpu->RegRead(REG_EIP, &eip); - DumpCPURegisters(m_cpu); + DumpCPURegisters(vp); #endif #if defined(_DEBUG) && 0 // Print current EIP and instruction static bool printEIP = false; - uint32_t eip; - m_cpu->RegRead(REG_EIP, &eip); - log_debug("%08x", eip); + RegValue eip; + vp.RegRead(Reg::EIP, eip); + log_debug("%08x", eip.u32); { char mem[16]; - if (m_cpu->VMemRead(eip, 16, mem)) { - m_cpu->MemRead(eip, 16, mem); + if (vp.LMemRead(eip.u32, 16, mem)) { + vp.MemRead(eip.u32, 16, mem); } ZydisDecoder decoder; @@ -675,17 +702,17 @@ int Xbox::RunCpu() #endif // Handle result - if (result != 0) { + if (result != VPExecutionStatus::OK) { log_error("Error occurred!\n"); if (LOG_LEVEL >= LOG_LEVEL_DEBUG) { - uint32_t eip; - m_cpu->RegRead(REG_EIP, &eip); - DumpCPURegisters(m_cpu); - DumpCPUStack(m_cpu); - DumpCPUMemory(m_cpu, eip, 0x40, true); - DumpCPUMemory(m_cpu, eip, 0x40, false); - DumpCPUDisassembly(m_cpu, eip, 0x40, true); - DumpCPUDisassembly(m_cpu, eip, 0x40, false); + RegValue eip; + vp.RegRead(Reg::EIP, eip); + DumpCPURegisters(vp); + DumpCPUStack(vp); + DumpCPUMemory(vp, eip.u32, 0x40, true); + DumpCPUMemory(vp, eip.u32, 0x40, false); + DumpCPUDisassembly(vp, eip.u32, 0x40, true); + DumpCPUDisassembly(vp, eip.u32, 0x40, false); } // Stop emulation Stop(); @@ -737,7 +764,7 @@ int Xbox::RunCpu() // Print kernel bugchecks and wait for input if (m_settings.emu_stopOnBugChecks && LocateKernelData()) { uint32_t bugCheckCode[5] = { 0 }; - if (m_cpu->VMemRead(m_kExp_KiBugCheckData, 5 * sizeof(uint32_t), &bugCheckCode) == 0) { + if (vp.LMemRead(m_kExp_KiBugCheckData, 5 * sizeof(uint32_t), &bugCheckCode) == 0) { if (bugCheckCode[0] != 0 && m_lastBugCheckCode != bugCheckCode[0]) { log_fatal("/!\\ ---------------------------- /!\\\n"); log_fatal("/!\\ System issued a BugCheck /!\\\n"); @@ -755,24 +782,24 @@ int Xbox::RunCpu() } // Handle reason for the CPU to exit - exit_info = m_cpu->GetExitInfo(); - switch (exit_info->reason) { - case CPU_EXIT_HLT: log_info("CPU halted\n"); Stop(); break; - case CPU_EXIT_SHUTDOWN: log_info("VM is shutting down\n"); Stop(); break; - case CPU_EXIT_ERROR: log_fatal("CPU encountered an error\n"); Stop(); break; - case CPU_EXIT_HW_BREAKPOINT: - case CPU_EXIT_SW_BREAKPOINT: + auto& exitInfo = vp.GetVMExitInfo(); + switch (exitInfo.reason) { + case VMExitReason::HLT: log_info("CPU halted\n"); Stop(); break; + case VMExitReason::Shutdown: log_info("VM is shutting down\n"); Stop(); break; + case VMExitReason::Error: log_fatal("CPU encountered an error\n"); Stop(); break; + case VMExitReason::HardwareBreakpoint: + case VMExitReason::SoftwareBreakpoint: { - uint32_t bpAddr; - if (m_cpu->GetBreakpointAddress(&bpAddr) == CPUS_OP_OK) { - if (exit_info->reason == CPU_EXIT_HW_BREAKPOINT) { + uint64_t bpAddr; + if (vp.GetBreakpointAddress(&bpAddr) == VPOperationStatus::OK) { + if (exitInfo.reason == VMExitReason::HardwareBreakpoint) { log_info("Hardware breakpoint hit at 0x%08x\n", bpAddr); } else { log_info("Software breakpoint hit at 0x%08x\n", bpAddr); } - DumpCPURegisters(m_cpu); - DumpCPUStack(m_cpu, -0x10, 0x100); + DumpCPURegisters(vp); + DumpCPUStack(vp, -0x10, 0x100); // TODO: allow users to handle breakpoints //log_warning("Press ENTER to continue\n"); //getchar(); @@ -789,21 +816,22 @@ int Xbox::RunCpu() } } - return result; + return result == VPExecutionStatus::OK ? 0 : 1; } void Xbox::Cleanup() { if (LOG_LEVEL >= LOG_LEVEL_DEBUG) { log_debug("CPU state at the end of execution:\n"); - uint32_t eip; - m_cpu->RegRead(REG_EIP, &eip); - DumpCPURegisters(m_cpu); + auto& vp = m_vm->get().GetVirtualProcessor(0)->get(); + RegValue eip; + vp.RegRead(Reg::EIP, eip); + DumpCPURegisters(vp); if (m_settings.debug_dumpStackOnExit) { - DumpCPUStack(m_cpu, -m_settings.debug_dumpStack_upperBound, m_settings.debug_dumpStack_lowerBound); + DumpCPUStack(vp, -m_settings.debug_dumpStack_upperBound, m_settings.debug_dumpStack_lowerBound); } if (m_settings.debug_dumpDisassemblyOnExit) { - DumpCPUDisassembly(m_cpu, eip, m_settings.debug_dumpDisassembly_length, true); - DumpCPUDisassembly(m_cpu, eip, m_settings.debug_dumpDisassembly_length, false); + DumpCPUDisassembly(vp, eip.u32, m_settings.debug_dumpDisassembly_length, true); + DumpCPUDisassembly(vp, eip.u32, m_settings.debug_dumpDisassembly_length, false); } #if 0 @@ -819,7 +847,7 @@ void Xbox::Cleanup() { uint8_t buf[0x10000]; uint32_t totalLen = 0; uint32_t len = 0; - while (m_cpu->VMemRead(0x80010000 + totalLen, sizeof(buf), buf, &len) == CPUS_OP_OK && len > 0) { + while (vp.LMemRead(0x80010000 + totalLen, sizeof(buf), buf, &len) == CPUS_OP_OK && len > 0) { totalLen += len; fwrite(buf, sizeof(uint8_t), len, fp); } @@ -830,25 +858,24 @@ void Xbox::Cleanup() { #endif if (m_settings.debug_dumpPageTables) { - uint32_t cr0; - m_cpu->RegRead(REG_CR0, &cr0); - if (cr0 & (CR0_PG | CR0_PE)) { + RegValue cr0; + vp.RegRead(Reg::CR0, cr0); + if (cr0.u32 & (CR0_PG | CR0_PE)) { log_debug("\nPage tables:\n"); - uint32_t cr3; - m_cpu->RegRead(REG_CR3, &cr3); - for (uint32_t pdeEntry = 0; pdeEntry < 0x1000; pdeEntry += sizeof(Pte)) { - Pte *pde; - uint32_t pdeAddr = cr3 + pdeEntry; - pde = (Pte *)&m_ram[pdeAddr]; + RegValue cr3; + vp.RegRead(Reg::CR3, cr3); + for (uint32_t pdeEntry = 0; pdeEntry < 0x1000; pdeEntry += sizeof(PDE32)) { + PDE32 *pde; + uint32_t pdeAddr = cr3.u32 + pdeEntry; + pde = (PDE32 *)&m_ram[pdeAddr]; char pdeFlags[] = "-----------"; - pdeFlags[0] = pde->persistAllocation ? 'P' : '-'; - pdeFlags[1] = pde->guardOrEndOfAllocation ? 'E' : '-'; + pdeFlags[0] = pde->persist ? 'P' : '-'; + pdeFlags[1] = pde->guard ? 'E' : '-'; pdeFlags[2] = pde->global ? 'G' : '-'; pdeFlags[3] = pde->largePage ? 'L' : '-'; pdeFlags[4] = pde->dirty ? 'D' : '-'; pdeFlags[5] = pde->accessed ? 'A' : '-'; - pdeFlags[6] = pde->cacheDisable ? 'N' : '-'; pdeFlags[7] = pde->writeThrough ? 'T' : '-'; pdeFlags[8] = pde->owner ? 'U' : 'K'; pdeFlags[9] = pde->write ? 'W' : 'R'; @@ -859,19 +886,19 @@ void Xbox::Cleanup() { uint32_t paddr = (pde->pageFrameNumber << 12); log_debug(" 0x%08x..0x%08x -> 0x%08x..0x%08x PDE 0x%08x [%s]\n", - vaddr, vaddr + MiB(4) - 1, - paddr, paddr + MiB(4) - 1, + vaddr, vaddr + 4*MiB - 1, + paddr, paddr + 4*MiB - 1, pdeAddr, pdeFlags); } else if (pde->valid) { - for (uint32_t pteEntry = 0; pteEntry < 0x1000; pteEntry += sizeof(Pte)) { - Pte *pte; + for (uint32_t pteEntry = 0; pteEntry < 0x1000; pteEntry += sizeof(PTE32)) { + PTE32 *pte; uint32_t pteAddr = (pde->pageFrameNumber << 12) + pteEntry; - pte = (Pte *)&m_ram[pteAddr]; + pte = (PTE32 *)&m_ram[pteAddr]; char pteFlags[] = "----------"; - pteFlags[0] = pte->persistAllocation ? 'P' : '-'; - pteFlags[1] = pte->guardOrEndOfAllocation ? 'E' : '-'; + pteFlags[0] = pte->persist ? 'P' : '-'; + pteFlags[1] = pte->guard ? 'E' : '-'; pteFlags[2] = pte->global ? 'G' : '-'; pteFlags[3] = pte->dirty ? 'D' : '-'; pteFlags[4] = pte->accessed ? 'A' : '-'; @@ -883,10 +910,10 @@ void Xbox::Cleanup() { if (pte->valid) { uint32_t vaddr = (pdeEntry << 20) | (pteEntry << 10); - uint32_t paddr = (pte->pageFrameNumber << 12) | (vaddr & (KiB(4) - 1)); + uint32_t paddr = (pte->pageFrameNumber << 12) | (vaddr & (4*KiB - 1)); log_debug(" 0x%08x..0x%08x -> 0x%08x..0x%08x PDE 0x%08x [%s] PTE 0x%08x [%s]\n", - vaddr, vaddr + KiB(4) - 1, - paddr, paddr + KiB(4) - 1, + vaddr, vaddr + 4*KiB - 1, + paddr, paddr + 4*KiB - 1, pdeAddr, pdeFlags, pteAddr, pteFlags); } @@ -916,11 +943,12 @@ bool Xbox::LocateKernelData() { } // Check if the kernel has been extracted and decrypted - uint32_t eip; - m_cpu->RegRead(REG_EIP, &eip); - if (eip >= 0x80000000) { + auto& vp = m_vm->get().GetVirtualProcessor(0)->get(); + RegValue eip; + vp.RegRead(Reg::EIP, eip); + if (eip.u32 >= 0x80000000) { uint16_t mzMagic = 0; - if (m_cpu->VMemRead(0x80010000, sizeof(uint16_t), &mzMagic)) return false; + if (vp.LMemRead(0x80010000, sizeof(uint16_t), &mzMagic)) return false; if (mzMagic != 0x5a4d) { return false; } @@ -931,39 +959,39 @@ bool Xbox::LocateKernelData() { uint32_t exportsTableAddress = 0x00000000; // Find PE header position and ensure it matches the magic value - if (m_cpu->VMemRead(0x8001003c, sizeof(uint32_t), &peHeaderAddress)) return false; + if (vp.LMemRead(0x8001003c, sizeof(uint32_t), &peHeaderAddress)) return false; peHeaderAddress += 0x80010000; uint16_t peMagic = 0; - if (m_cpu->VMemRead(peHeaderAddress, sizeof(uint16_t), &peMagic)) return false; + if (vp.LMemRead(peHeaderAddress, sizeof(uint16_t), &peMagic)) return false; if (peMagic != 0x4550) { peHeaderAddress = 0x00000000; return false; } // Find base of code and address of functions to locate the exports table - if (m_cpu->VMemRead(peHeaderAddress + 0x2c, sizeof(uint32_t), &baseOfCode)) return false; + if (vp.LMemRead(peHeaderAddress + 0x2c, sizeof(uint32_t), &baseOfCode)) return false; baseOfCode += 0x80010000; // Find exports table - if (m_cpu->VMemRead(baseOfCode + 0x1c, sizeof(uint32_t), &exportsTableAddress)) return false; + if (vp.LMemRead(baseOfCode + 0x1c, sizeof(uint32_t), &exportsTableAddress)) return false; exportsTableAddress += 0x80010000; // Get addresses of relevant exports -#define GET_EXPORT(name, num) do { if (m_cpu->VMemRead(exportsTableAddress + ((num - 1) * sizeof(uint32_t)), sizeof(uint32_t), &m_kExp_##name)) { return false; } m_kExp_##name += 0x80010000; } while (0) +#define GET_EXPORT(name, num) do { if (vp.LMemRead(exportsTableAddress + ((num - 1) * sizeof(uint32_t)), sizeof(uint32_t), &m_kExp_##name)) { return false; } m_kExp_##name += 0x80010000; } while (0) GET_EXPORT(KiBugCheckData, 162); GET_EXPORT(XboxKrnlVersion, 324); #undef GET_EXPORT - uint32_t pKernelPEHeaderPos; - uint32_t pKernelBaseOfCode; - uint32_t pKernelExportsTableAddress; - uint32_t pKiBugCheckData; - uint32_t pXboxKrnlVersion; - m_cpu->VirtualToPhysical(peHeaderAddress, &pKernelPEHeaderPos); - m_cpu->VirtualToPhysical(baseOfCode, &pKernelBaseOfCode); - m_cpu->VirtualToPhysical(exportsTableAddress, &pKernelExportsTableAddress); - m_cpu->VirtualToPhysical(m_kExp_KiBugCheckData, &pKiBugCheckData); - m_cpu->VirtualToPhysical(m_kExp_XboxKrnlVersion, &pXboxKrnlVersion); + uint64_t pKernelPEHeaderPos; + uint64_t pKernelBaseOfCode; + uint64_t pKernelExportsTableAddress; + uint64_t pKiBugCheckData; + uint64_t pXboxKrnlVersion; + vp.LinearToPhysical(peHeaderAddress, &pKernelPEHeaderPos); + vp.LinearToPhysical(baseOfCode, &pKernelBaseOfCode); + vp.LinearToPhysical(exportsTableAddress, &pKernelExportsTableAddress); + vp.LinearToPhysical(m_kExp_KiBugCheckData, &pKiBugCheckData); + vp.LinearToPhysical(m_kExp_XboxKrnlVersion, &pXboxKrnlVersion); log_info("Microsoft Xbox Kernel detected\n"); log_info(" PE header 0x%08x -> 0x%p\n", peHeaderAddress, m_ram + pKernelPEHeaderPos); log_info(" Base of code 0x%08x -> 0x%p\n", baseOfCode, m_ram + pKernelBaseOfCode); @@ -972,7 +1000,7 @@ bool Xbox::LocateKernelData() { log_info(" XboxKrnlVersion 0x%08x -> 0x%p\n", m_kExp_XboxKrnlVersion, m_ram + pXboxKrnlVersion); m_kernelDataFound = true; - m_cpu->VMemRead(m_kExp_XboxKrnlVersion, sizeof(XboxKernelVersion), &m_kernelVersion); + vp.LMemRead(m_kExp_XboxKrnlVersion, sizeof(XboxKernelVersion), &m_kernelVersion); log_info("Xbox kernel version: %d.%d.%d.%d\n", m_kernelVersion.major, m_kernelVersion.minor, m_kernelVersion.build, m_kernelVersion.rev); return true; diff --git a/src/common/vixen/linux/thread.cpp b/modules/core/src/linux/thread.cpp similarity index 100% rename from src/common/vixen/linux/thread.cpp rename to modules/core/src/linux/thread.cpp diff --git a/src/common/vixen/win32/thread.cpp b/modules/core/src/windows/thread.cpp similarity index 100% rename from src/common/vixen/win32/thread.cpp rename to modules/core/src/windows/thread.cpp diff --git a/src/core/vixen/hw/basic/win32/char_serial.cpp b/modules/core/src/windows/vixen/hw/basic/win32/char_serial.cpp similarity index 100% rename from src/core/vixen/hw/basic/win32/char_serial.cpp rename to modules/core/src/windows/vixen/hw/basic/win32/char_serial.cpp diff --git a/src/core/vixen/hw/basic/win32/char_serial.h b/modules/core/src/windows/vixen/hw/basic/win32/char_serial.h similarity index 95% rename from src/core/vixen/hw/basic/win32/char_serial.h rename to modules/core/src/windows/vixen/hw/basic/win32/char_serial.h index d4fab16..3284c53 100644 --- a/src/core/vixen/hw/basic/win32/char_serial.h +++ b/modules/core/src/windows/vixen/hw/basic/win32/char_serial.h @@ -1,6 +1,6 @@ #pragma once -#include "../char.h" +#include "vixen/hw/basic/char.h" #include "vixen/thread.h" #include "mt_serial.h" diff --git a/src/core/vixen/hw/basic/win32/mt_serial.cpp b/modules/core/src/windows/vixen/hw/basic/win32/mt_serial.cpp similarity index 100% rename from src/core/vixen/hw/basic/win32/mt_serial.cpp rename to modules/core/src/windows/vixen/hw/basic/win32/mt_serial.cpp diff --git a/src/core/vixen/hw/basic/win32/mt_serial.h b/modules/core/src/windows/vixen/hw/basic/win32/mt_serial.h similarity index 100% rename from src/core/vixen/hw/basic/win32/mt_serial.h rename to modules/core/src/windows/vixen/hw/basic/win32/mt_serial.h diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt deleted file mode 100644 index 77104f7..0000000 --- a/src/cli/CMakeLists.txt +++ /dev/null @@ -1,88 +0,0 @@ -# Add sources -file(GLOB DIR_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/*.h - ) - -file(GLOB DIR_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp - ) - -set(SOURCES ${SOURCES} - ${DIR_HEADERS} - ${DIR_SOURCES} - ) - -add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/lib") - -# Add Visual Studio filters to better organize the code -vs_set_filters("${SOURCES}") - -# Main Executable -if(NOT MSVC) - add_definitions("-Wall -Werror -O0 -g") -endif() -add_executable(cli ${SOURCES}) -target_include_directories(cli PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - -# Include viXen core -target_link_libraries(cli core) - -# Name the output file "vixen-cli" -set_target_properties(cli PROPERTIES OUTPUT_NAME "vixen-cli") - -# Make the Debug and RelWithDebInfo targets use Program Database for Edit and Continue for easier debugging -vs_use_edit_and_continue() - -# Set the working directory to the path where the executable file is deployed -if(MSVC) - set_target_properties(cli PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") -endif() - -# Add custom build commands to copy modules to the command line front-end build output directory -if(MSVC) - set(CPU_MODULE "none" CACHE STRING "Choose a CPU module to use: haxm, whvp, none") - - # Create modules directory - add_custom_command(TARGET cli - POST_BUILD - COMMAND if not exist \"$(TargetDir)modules\" mkdir \"$(TargetDir)modules\") - - # Include libraries and copy module DLLs according to user option - string(TOLOWER ${CPU_MODULE} CPU_MODULE_LC) - if(CPU_MODULE_LC STREQUAL haxm) - message(STATUS "CLI front-end will use Intel HAXM CPU module") - target_link_libraries(cli cpu-module-haxm) - elseif(CPU_MODULE_LC STREQUAL whvp) - message(STATUS "CLI front-end will use Windows Hypervisor Platform CPU module") - target_link_libraries(cli cpu-module-whvp) - elseif(CPU_MODULE_LC STREQUAL none) - message(WARNING "No CPU module specified. viXen requires at least one CPU module to run. " - "Make sure to add one to the module subdirectory in the build output directory, or set the CPU_MODULE option to one of the available options.") - else() - message(SEND_ERROR "Invalid CPU module specified. Check your CPU_MODULE option.") - endif() -elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - set(CPU_MODULE "none" CACHE STRING "Choose a CPU module to use: kvm, none") - - add_custom_command(TARGET cli - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/src/cli/modules) - - # Include libraries according to user option - string(TOLOWER ${CPU_MODULE} CPU_MODULE_LC) - if(CPU_MODULE_LC STREQUAL kvm) - message(STATUS "CLI front-end will use KVM CPU module") - target_link_libraries(cli cpu-module-kvm) - elseif(CPU_MODULE_LC STREQUAL none) - message(WARNING "No CPU module specified. viXen requires at least one CPU module to run. " - "Make sure to add one to the module subdirectory in the build output directory, or set the CPU_MODULE option to one of the available options.") - else() - message(SEND_ERROR "Invalid CPU module specified. Check your CPU_MODULE option.") - endif() -endif() - -# Include additional libraries on GCC -if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - find_package(Threads REQUIRED) - target_link_libraries(cli -lstdc++fs ${CMAKE_THREAD_LIBS_INIT}) -endif() diff --git a/src/cli/lib/CMakeLists.txt b/src/cli/lib/CMakeLists.txt deleted file mode 100644 index 0a36fe8..0000000 --- a/src/cli/lib/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -file(GLOB DIR_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp - ) - -file(GLOB DIR_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp - ) - -set(SOURCES ${SOURCES} - ${DIR_HEADERS} - ${DIR_SOURCES} - PARENT_SCOPE - ) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt deleted file mode 100644 index 102961c..0000000 --- a/src/common/CMakeLists.txt +++ /dev/null @@ -1,39 +0,0 @@ -file(GLOB DIR_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/vixen/*.h - ) - -file(GLOB DIR_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/vixen/*.cpp - ) - -set(SOURCES ${SOURCES} - ${DIR_HEADERS} - ${DIR_SOURCES} - ) - -if (WIN32) - add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/vixen/win32") -endif () -if (UNIX) - add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/vixen/linux") -endif () - -# Add Visual Studio filters to better organize the code -vs_set_filters("${SOURCES}" "vixen") - -# Main Executable -if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - add_definitions("-Wall -Werror -O0 -g -fPIC") -endif() - -add_library(common STATIC ${SOURCES}) -target_include_directories(common PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - -# Include ld -if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - target_link_libraries(common ${CMAKE_DL_LIBS}) -endif() - -# Make the Debug and RelWithDebInfo targets use Program Database for Edit and Continue for easier debugging -vs_use_edit_and_continue() - diff --git a/src/common/vixen/bitmap.h b/src/common/vixen/bitmap.h deleted file mode 100644 index 42448f7..0000000 --- a/src/common/vixen/bitmap.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include - -namespace vixen { - -#define BITMASK64(bit) (1ULL << (uint64_t)(bit)) - -typedef uint64_t Bitmap64; - -/*! - * Determines if a bit is set in the 64-bit bitmap. - */ -inline bool Bitmap64IsSet(Bitmap64 bitmap, uint8_t bit) { - return (bitmap & BITMASK64(bit)) != 0; -} - -/*! - * Sets a bit in the 64-bit bitmap. - */ -inline void Bitmap64Set(Bitmap64 *bitmap, uint8_t bit) { - *bitmap |= BITMASK64(bit); -} - -/*! - * Clears a bit in the 64-bit bitmap. - */ -inline void Bitmap64Clear(Bitmap64 *bitmap, uint8_t bit) { - *bitmap &= ~BITMASK64(bit); -} - -} \ No newline at end of file diff --git a/src/common/vixen/gdt.cpp b/src/common/vixen/gdt.cpp deleted file mode 100644 index 6f47b03..0000000 --- a/src/common/vixen/gdt.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "gdt.h" - -namespace vixen { - -void _GDTEntry::Set(uint32_t base, uint32_t limit, uint8_t access, uint8_t flags) { - this->descriptor = 0ULL; - - this->data.baseLow = base & 0xFFFF; - this->data.baseMid = (base >> 16) & 0xFF; - this->data.baseHigh = (base >> 24); - - this->data.limitLow = limit & 0xFFFF; - this->data.limitHigh = (limit >> 16) & 0xF; - - this->data.access = access; - this->data.flags = flags & 0xF; -} - -} diff --git a/src/common/vixen/gdt.h b/src/common/vixen/gdt.h deleted file mode 100644 index b088dc7..0000000 --- a/src/common/vixen/gdt.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include - -namespace vixen { - -typedef struct _GDTEntry { - union { - struct { - uint16_t limitLow : 16; - uint16_t baseLow : 16; - uint8_t baseMid : 8; - uint8_t access : 8; - uint8_t limitHigh : 4; - uint8_t flags : 4; - uint8_t baseHigh : 8; - } data; - uint64_t descriptor; - }; - - void Set(uint32_t base, uint32_t limit, uint8_t access, uint8_t flags); - - uint32_t GetBase() { - return ((data.baseLow) | (data.baseMid << 16) | (data.baseHigh << 24)); - } - - uint32_t GetLimit() { - uint32_t limit = ((data.limitLow) | (data.limitHigh << 16)); - // If we use 4 KB pages, extend the limit to reflect that - if (data.flags & 0x8) { - limit = (limit << 12) | 0xfff; - } - return limit; - } - -} GDTEntry; - -} diff --git a/src/common/vixen/idt.cpp b/src/common/vixen/idt.cpp deleted file mode 100644 index 1906085..0000000 --- a/src/common/vixen/idt.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "idt.h" - -namespace vixen { - -void _IDTEntry::Set(uint32_t offset, uint16_t selector, uint8_t type, uint8_t attributes) { - this->descriptor = 0ULL; - - this->data.offsetLow = offset & 0xFFFF; - this->data.offsetHigh = (offset >> 16); - - this->data.selector = selector; - - this->data.type = type & 0xF; - this->data.storageSegment = attributes & 0x1; - this->data.privilegeLevel = (attributes >> 1) & 0x3; - this->data.present = (attributes >> 3) & 0x1; -} - -uint32_t _IDTEntry::GetOffset() { - return ((uint32_t)data.offsetLow) | (((uint32_t)data.offsetHigh) << 16); -} - -void _IDTEntry::SetOffset(uint32_t offset) { - this->data.offsetLow = offset & 0xFFFF; - this->data.offsetHigh = (offset >> 16); -} - -} diff --git a/src/common/vixen/idt.h b/src/common/vixen/idt.h deleted file mode 100644 index 6f37911..0000000 --- a/src/common/vixen/idt.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include - -namespace vixen { - -const uint8_t kIDTG_Null00 = 0x0; -const uint8_t kIDTG_Task32 = 0x5; -const uint8_t kIDTG_Intr32 = 0xE; -const uint8_t kIDTG_Trap32 = 0xF; - -typedef struct _IDTEntry { - union { - struct { - uint16_t offsetLow : 16; - uint16_t selector: 16; - uint8_t zero : 8; - uint8_t type : 4; - uint8_t storageSegment : 1; - uint8_t privilegeLevel : 2; - uint8_t present : 1; - uint16_t offsetHigh : 16; - } data; - uint64_t descriptor; - }; - - void Set(uint32_t offset, uint16_t selector, uint8_t type, uint8_t attributes); - uint32_t GetOffset(); - void SetOffset(uint32_t offset); -} IDTEntry; - -} diff --git a/src/common/vixen/linux/CMakeLists.txt b/src/common/vixen/linux/CMakeLists.txt deleted file mode 100644 index 9ab3420..0000000 --- a/src/common/vixen/linux/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -file(GLOB DIR_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/*.h - ) - -file(GLOB DIR_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp - ) - -set(SOURCES ${SOURCES} - ${DIR_HEADERS} - ${DIR_SOURCES} - PARENT_SCOPE - ) diff --git a/src/common/vixen/linux/shlibrary.cpp b/src/common/vixen/linux/shlibrary.cpp deleted file mode 100644 index 644a31d..0000000 --- a/src/common/vixen/linux/shlibrary.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#if defined(__linux__) || defined(LINUX) - -#include "vixen/shlibrary.h" -#include "vixen/log.h" - -#include - -namespace vixen { - -class LinuxSharedLibrary : public SharedLibrary { -public: - // TODO: implement - LinuxSharedLibrary(void *libHandle); - ~LinuxSharedLibrary(); - - void *GetExport(std::string exportName); -private: - void *m_libHandle; -}; - -SharedLibraryStatus SharedLibrary_Load(std::wstring path, SharedLibrary **library) { - char *pathStr = new char[path.size()+1]; - wcstombs(pathStr, path.c_str(), path.size()); - - void *libHandle = ::dlopen(pathStr, RTLD_LAZY); - - delete[] pathStr; - if (libHandle == nullptr) { - log_error("%s\n", dlerror()); - return kLibraryUnspecifiedError; - } - *library = new LinuxSharedLibrary(libHandle); - return kLibraryLoadSuccess; -} - -LinuxSharedLibrary::LinuxSharedLibrary(void *libHandle) - : m_libHandle(libHandle) -{ -} - -LinuxSharedLibrary::~LinuxSharedLibrary() { -} - -void *LinuxSharedLibrary::GetExport(std::string exportName) { - // The correct way to check if the symbols exists and is not just NULL is - // to execute dlerror(), then save the result of dlsym() to a variable, - // then check if dlerror() is NULL. If it is, the symbol does not exist. - - // However, since GetExport doesn't care about the existence of the symbol, - // we simply return the result of dlsym(). - return ::dlsym(m_libHandle, exportName.c_str()); -} - -} - -#endif // LINUX - diff --git a/src/common/vixen/memregion.h b/src/common/vixen/memregion.h deleted file mode 100644 index 4fbe1b3..0000000 --- a/src/common/vixen/memregion.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include -#include - -namespace vixen { - -class MemoryRegion; - -/*! - * Memory Region Type enumeration - */ -enum MemoryRegionType -{ - MEM_REGION_NONE, // Region type is unspecified (may have multiple sub types) - MEM_REGION_RAM, // Region is RAM - MEM_REGION_MMIO, // Region is Memory-Mapped IO - MEM_REGION_ROM, // Region is ROM -}; - -/*! - * Memory Region Event Type enumeration - */ -enum MemoryRegionEventType -{ - MEM_EVENT_READ, - MEM_EVENT_WRITE, - MEM_EVENT_EXECUTE, -}; - -/*! - * Memory Region Event - */ -struct MemoryRegionEvent { - enum MemoryRegionEventType type; - uint32_t addr; - size_t size; - uint64_t value; -}; - -/*! - * Memory Region singly-linked list - */ -struct MemoryRegionLink { - MemoryRegion *curr; - MemoryRegionLink *next; -}; - -/*! - * Memory event handler function pointer prototype - */ -typedef int (*MemoryRegionEventHandler)(MemoryRegion *region, struct MemoryRegionEvent *event, void *user_data); - -/*! - * Generic memory region - * - * This class is used to classify the various regions of memory. Subregions - * can be added to regions for further classification. - */ -class MemoryRegion -{ -public: - MemoryRegion *m_parent; - MemoryRegionLink *m_subregions; - enum MemoryRegionType m_type; - uint32_t m_start; - size_t m_size; - void *m_data; - MemoryRegionEventHandler m_handler; - void *m_handler_user; - - MemoryRegion(enum MemoryRegionType type, uint32_t start, size_t size, void *data); - ~MemoryRegion(); - uint32_t GetAbsoluteAddress(uint32_t offset); - void SetParent(MemoryRegion *parent); - void SetEventHandler(MemoryRegionEventHandler handler, void *user_data); - int AddSubRegion(MemoryRegion *region); -}; - -} diff --git a/src/common/vixen/platform.h b/src/common/vixen/platform.h deleted file mode 100644 index 50ea8ef..0000000 --- a/src/common/vixen/platform.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -// Check windows -#if _WIN32 || _WIN64 -#if _WIN64 -#define ENVIRONMENT64 -#else -#define ENVIRONMENT32 -#endif -#endif - -// Check GCC -#if __GNUC__ -#if __x86_64__ || __ppc64__ -#define ENVIRONMENT64 -#else -#define ENVIRONMENT32 -#endif -#endif diff --git a/src/common/vixen/pte.h b/src/common/vixen/pte.h deleted file mode 100644 index b77904e..0000000 --- a/src/common/vixen/pte.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include - -namespace vixen { - -#define ONE_KB 1024 -#define ONE_MB (1024 * 1024) - -#define XBOX_MEMORY_SIZE (64 * ONE_MB) - -#define XBE_IMAGE_BASE 0x00010000 -#define CONTIGUOUS_MEMORY_BASE 0x80000000 - -struct Pte { - uint32_t valid : 1; - uint32_t write : 1; - uint32_t owner : 1; - uint32_t writeThrough : 1; - uint32_t cacheDisable : 1; - uint32_t accessed : 1; - uint32_t dirty : 1; - uint32_t largePage : 1; - uint32_t global : 1; - uint32_t guardOrEndOfAllocation : 1; - uint32_t persistAllocation : 1; - uint32_t _reserved : 1; - uint32_t pageFrameNumber : 20; -}; - -} diff --git a/src/common/vixen/shlibrary.cpp b/src/common/vixen/shlibrary.cpp deleted file mode 100644 index 36c2b89..0000000 --- a/src/common/vixen/shlibrary.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "vixen/shlibrary.h" - -namespace vixen { - -SharedLibrary::~SharedLibrary() { -} - -} - diff --git a/src/common/vixen/shlibrary.h b/src/common/vixen/shlibrary.h deleted file mode 100644 index 06b6b59..0000000 --- a/src/common/vixen/shlibrary.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include -#include - -namespace vixen { - -// ----- Library load status -------------------------------------------------- - -/*! - * Indicates the result of attempting to load a library. - */ -typedef int32_t SharedLibraryStatus; - -// The shared library was loaded successfully -const SharedLibraryStatus kLibraryLoadSuccess = 0x00000000; - -// The shared library could not be found at the specified path -const SharedLibraryStatus kLibraryNotFound = 0x80000001; - -// The file specified is not a valid shared library image -const SharedLibraryStatus kLibraryInvalidImage = 0x80000002; - -// An unspecified error occurred while trying to load the shared library -const SharedLibraryStatus kLibraryUnspecifiedError = 0xFFFFFFFF; - -// ----- Library class -------------------------------------------------------- - -/*! - * A shared library loaded into the application. - */ -class SharedLibrary { -public: - virtual ~SharedLibrary(); - - virtual void *GetExport(std::string exportName) = 0; -}; - -// ----- Library functions ---------------------------------------------------- - -/*! - * Loads a shared library from the specified path. - * Returns nullptr if the library fails to load. - */ -SharedLibraryStatus SharedLibrary_Load(std::wstring path, SharedLibrary **library); - - -} diff --git a/src/common/vixen/status.h b/src/common/vixen/status.h deleted file mode 100644 index 6a88c53..0000000 --- a/src/common/vixen/status.h +++ /dev/null @@ -1,74 +0,0 @@ -#pragma once - -namespace vixen { - -enum EmulatorStatus { - EMUS_OK = 0, // Operation completed successfully - - EMUS_INIT_INVALID_REVISION, // An invalid hardware revision was specified - - EMUS_INIT_ALLOC_MEM_RGN_FAILED, // Could not allocate memory for the global memory region - - EMUS_INIT_ALLOC_RAM_FAILED, // Could not allocate memory for the guest RAM - EMUS_INIT_ALLOC_RAM_RGN_FAILED, // Could not allocate memory for the RAM region - - EMUS_INIT_ALLOC_ROM_FAILED, // Could not allocate memory for the guest ROM - EMUS_INIT_ALLOC_ROM_RGN_FAILED, // Could not allocate memory for the ROM region - EMUS_INIT_MCPX_ROM_NOT_FOUND, // MCPX ROM file not found - EMUS_INIT_MCPX_ROM_INVALID_SIZE, // MCPX ROM provided has incorrect size (must be 512 bytes) - EMUS_INIT_BIOS_ROM_NOT_FOUND, // BIOS ROM file not found - EMUS_INIT_BIOS_ROM_INVALID_SIZE, // BIOS ROM provided has incorrect size (must be 256 KiB or 1 MiB) - - EMUS_INIT_NO_CPU_MODULE, // No CPU module specified - EMUS_INIT_CPU_CREATE_FAILED, // CPU instantiation failed - EMUS_INIT_CPU_INIT_FAILED, // CPU initialization failed - EMUS_INIT_CPU_MEM_MAP_FAILED, // Memory mapping failed - - EMUS_INIT_INVALID_HARD_DRIVE_TYPE, // An invalid hard drive type was specified - EMUS_INIT_HARD_DRIVE_INIT_FAILED, // Virtual hard drive initialization failed - EMUS_INIT_INVALID_DVD_DRIVE_TYPE, // An invalid DVD drive type was specified - EMUS_INIT_DVD_DRIVE_INIT_FAILED, // Virtual DVD drive initialization failed - - EMUS_INIT_DEBUGGER_FAILED, // Debugger initialization failed -}; - -enum CPUInitStatus { - CPUS_INIT_OK = 0, // CPU initialized successfully - - CPUS_INIT_PLATFORM_INIT_FAILED, // Failed to initialize emulation or virtualization platform - CPUS_INIT_CREATE_VM_FAILED, // Failed to create virtual machine - CPUS_INIT_CREATE_CPU_FAILED, // Failed to create CPU -}; - -enum CPUStatus { - CPUS_OK = 0, // CPU executed successfully - - CPUS_FAILED, // CPU emulation failed due to an unspecified error - CPUS_UNSUPPORTED, // CPU emulator does not support the operation -}; - -enum CPUMemMapStatus { - CPUS_MMAP_OK = 0, // Memory mapped successfully - - CPUS_MMAP_CPU_UNINITIALIZED, // The virtual CPU is not initialized - CPUS_MMAP_INVALID_TYPE, // Invalid memory region type - CPUS_MMAP_MEMORY_ADDR_MISALIGNED, // The provided memory region is misaligned - CPUS_MMAP_MEMORY_SIZE_MISALIGNED, // The provided memory region size is misaligned - CPUS_MMAP_MAPPING_FAILED, // Failed to map the memory region - - CPUS_MMAP_UNHANDLED_ERROR, // An unhandled error occurred -}; - -enum CPUOperationStatus { - CPUS_OP_OK = 0, // Operation completed succesfully - - CPUS_OP_FAILED, // The operation failed - CPUS_OP_INVALID_ADDRESS, // An invalid memory address was specified - CPUS_OP_INVALID_SELECTOR, // An invalid selector was specified - CPUS_OP_INVALID_REGISTER, // An invalid register was specified - CPUS_OP_BREAKPOINT_NEVER_HIT, // A breakpoint was never hit - - CPUS_OP_UNSUPPORTED, // The operation is not supported -}; - -} diff --git a/src/common/vixen/win32/CMakeLists.txt b/src/common/vixen/win32/CMakeLists.txt deleted file mode 100644 index 9ab3420..0000000 --- a/src/common/vixen/win32/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -file(GLOB DIR_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/*.h - ) - -file(GLOB DIR_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp - ) - -set(SOURCES ${SOURCES} - ${DIR_HEADERS} - ${DIR_SOURCES} - PARENT_SCOPE - ) diff --git a/src/common/vixen/win32/shlibrary.cpp b/src/common/vixen/win32/shlibrary.cpp deleted file mode 100644 index 3eed3f7..0000000 --- a/src/common/vixen/win32/shlibrary.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifdef _WIN32 - -#include "vixen/shlibrary.h" - -#include - -namespace vixen { - -class Win32SharedLibrary : public SharedLibrary { -public: - Win32SharedLibrary(HMODULE hm); - ~Win32SharedLibrary(); - - void *GetExport(std::string exportName); -private: - HMODULE m_hm; -}; - -SharedLibraryStatus SharedLibrary_Load(std::wstring path, SharedLibrary **library) { - HMODULE hm = LoadLibraryW(path.c_str()); - if (hm == NULL) { - DWORD lastError = GetLastError(); - switch (lastError) { - case ERROR_MOD_NOT_FOUND: - return kLibraryNotFound; - case ERROR_BAD_EXE_FORMAT: - return kLibraryInvalidImage; - default: - return kLibraryUnspecifiedError; - } - } - - *library = new Win32SharedLibrary(hm); - return kLibraryLoadSuccess; -} - -Win32SharedLibrary::Win32SharedLibrary(HMODULE hm) - : m_hm(hm) -{ -} - -Win32SharedLibrary::~Win32SharedLibrary() { - FreeLibrary(m_hm); -} - -void *Win32SharedLibrary::GetExport(std::string exportName) { - return GetProcAddress(m_hm, exportName.c_str()); -} - -} - -#endif diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt deleted file mode 100644 index 47d08de..0000000 --- a/src/core/CMakeLists.txt +++ /dev/null @@ -1,60 +0,0 @@ -file(GLOB DIR_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/vixen/*.h - ) - -file(GLOB DIR_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/vixen/*.cpp - ) - -add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/vixen/hw") -add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/vixen/util") - -set(SOURCES ${SOURCES} - ${DIR_HEADERS} - ${DIR_SOURCES} - ) - -include("${CMAKE_SOURCE_DIR}/cmake/PrecompiledHeader.cmake") -include(ExternalProject) - -# Add Visual Studio filters to better organize the code -vs_set_filters("${SOURCES}" "vixen") - -# Main Executable -if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - add_definitions("-Wall -Werror -O0 -g") -endif() -add_library(core STATIC - ${SOURCES} - "${CMAKE_CURRENT_SOURCE_DIR}/vixen/pch.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/vixen/pch.h") - -# Use precompiled headers to speed up compilation -add_precompiled_header(core vixen/pch.h FORCEINCLUDE SOURCE_CXX "${CMAKE_CURRENT_SOURCE_DIR}/vixen/pch.cpp") - -# Include Zydis -add_definitions(-DZYDIS_STATIC_DEFINE) -ExternalProject_Add( - Zydis - GIT_REPOSITORY "https://github.com/zyantific/zydis" - GIT_TAG "v2.0.0" - UPDATE_COMMAND "" - INSTALL_COMMAND "") -ExternalProject_Get_Property(Zydis install_dir) -include_directories(${install_dir}/src/Zydis/include ${install_dir}/src/Zydis-build) -add_dependencies(core Zydis) - -if(WIN32) - target_link_libraries(core ${install_dir}/src/Zydis-build/${CMAKE_CFG_INTDIR}/Zydis.lib) -else() - target_link_libraries(core ${install_dir}/src/Zydis-build/libZydis.a) -endif() - -target_include_directories(core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${install_dir}/src/Zydis/include) - -# Include viXen module interfaces -target_link_libraries(core common cpu-module) - -# Make the Debug and RelWithDebInfo targets use Program Database for Edit and Continue for easier debugging -vs_use_edit_and_continue() - diff --git a/src/core/vixen/.gitignore b/src/core/vixen/.gitignore deleted file mode 100644 index cc8cf39..0000000 --- a/src/core/vixen/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -vixen -*.o -*.bin -*.list -*.xbe diff --git a/src/core/vixen/debug.cpp b/src/core/vixen/debug.cpp deleted file mode 100644 index d1fd72b..0000000 --- a/src/core/vixen/debug.cpp +++ /dev/null @@ -1,188 +0,0 @@ -#include "debug.h" -#include - -namespace vixen { - -using namespace vixen::cpu; - -static void parseEFlags(uint32_t flags, char *str) { - str[0] = 0; - if (flags & CF_MASK ) { strcat(str, "CF "); } - if (flags & PF_MASK ) { strcat(str, "PF "); } - if (flags & AF_MASK ) { strcat(str, "AF "); } - if (flags & ZF_MASK ) { strcat(str, "ZF "); } - if (flags & SF_MASK ) { strcat(str, "SF "); } - if (flags & TF_MASK ) { strcat(str, "TF "); } - if (flags & IF_MASK ) { strcat(str, "IF "); } - if (flags & DF_MASK ) { strcat(str, "DF "); } - if (flags & OF_MASK ) { strcat(str, "OF "); } - if (flags & NT_MASK ) { strcat(str, "NT "); } - if (flags & RF_MASK ) { strcat(str, "RF "); } - if (flags & VM_MASK ) { strcat(str, "VM "); } - if (flags & AC_MASK ) { strcat(str, "AC "); } - if (flags & VIF_MASK) { strcat(str, "VIF "); } - if (flags & VIP_MASK) { strcat(str, "VIP "); } - strcat(str, "IOPL#"); - auto index = strlen(str) - 1; - str[index] = ((flags & IOPL_MASK) >> IOPL_BIT0) + '0'; -} - -static void parseCR0Flags(uint32_t flags, char *str) { - str[0] = 0; - if (flags & CR0_PG) { strcat(str, "PG "); } - if (flags & CR0_CD) { strcat(str, "CD "); } - if (flags & CR0_NW) { strcat(str, "NW "); } - if (flags & CR0_AM) { strcat(str, "AM "); } - if (flags & CR0_WP) { strcat(str, "WP "); } - if (flags & CR0_NE) { strcat(str, "NE "); } - if (flags & CR0_ET) { strcat(str, "ET "); } - if (flags & CR0_TS) { strcat(str, "TS "); } - if (flags & CR0_EM) { strcat(str, "EM "); } - if (flags & CR0_MP) { strcat(str, "MP "); } - if (flags & CR0_PE) { strcat(str, "PE "); } - if (flags) { str[strlen(str) - 1] = 0; } -} - -static void parseCR4Flags(uint32_t flags, char *str) { - str[0] = 0; - if (flags & CR4_VME) { strcat(str, "VME "); } - if (flags & CR4_PVI) { strcat(str, "PVI "); } - if (flags & CR4_TSD) { strcat(str, "TSD "); } - if (flags & CR4_DE ) { strcat(str, "DE "); } - if (flags & CR4_PSE) { strcat(str, "PSE "); } - if (flags & CR4_PAE) { strcat(str, "PAE "); } - if (flags & CR4_MCE) { strcat(str, "MCE "); } - if (flags & CR4_PGE) { strcat(str, "PGE "); } - if (flags & CR4_FXSR) { strcat(str, "FXSR "); } - if (flags & CR4_XMMEXCPT) { strcat(str, "XMMEXCPT "); } - if (flags) { str[strlen(str) - 1] = 0; } -} - - -void DumpCPURegisters(Cpu *cpu) { - char temp[128]; - - CpuReg regs[] = { - REG_CS, REG_EIP, REG_EBP, - REG_SS, REG_EAX, REG_ESP, - REG_DS, REG_ECX, REG_CR0, - REG_ES, REG_EDX, REG_CR2, - REG_FS, REG_EBX, REG_CR3, - REG_GS, REG_ESI, REG_CR4, - REG_TR, REG_EDI, REG_EFLAGS, - }; - uint32_t vals[ARRAY_SIZE(regs)]; - - cpu->RegRead(regs, vals, ARRAY_SIZE(regs)); - - /* */ log_debug("CPU registers:\n"); - /* */ log_debug(" CS = %04x EIP = %08x EBP = %08x\n", vals[0], vals[1], vals[2]); - /* */ log_debug(" SS = %04x EAX = %08x ESP = %08x\n", vals[3], vals[4], vals[5]); - parseCR0Flags(vals[8], temp); log_debug(" DS = %04x ECX = %08x CR0 = %08x %s\n", vals[6], vals[7], vals[8], temp); - /* */ log_debug(" ES = %04x EDX = %08x CR2 = %08x\n", vals[9], vals[10], vals[11]); - /* */ log_debug(" FS = %04x EBX = %08x CR3 = %08x\n", vals[12], vals[13], vals[14]); - parseCR4Flags(vals[17], temp); log_debug(" GS = %04x ESI = %08x CR4 = %08x %s\n", vals[15], vals[16], vals[17], temp); - parseEFlags(vals[20], temp); log_debug(" TR = %04x EDI = %08x EFL = %08x %s\n", vals[18], vals[19], vals[20], temp); - - - uint32_t base; - uint32_t limit; - cpu->GetGDT(&base, &limit); log_debug("GDT = %08x:%04x\n", base, limit); - cpu->GetIDT(&base, &limit); log_debug("IDT = %08x:%04x\n", base, limit); - log_debug("\n"); -} - -void DumpCPUStack(Cpu *cpu, int32_t offsetStart, int32_t offsetEnd) { - uint32_t esp; - uint32_t ebp; - cpu->RegRead(REG_ESP, &esp); - cpu->RegRead(REG_EBP, &ebp); - log_debug("Stack:\n"); - for (int i = offsetStart; i <= offsetEnd; i += 0x4) { - uint32_t val; - CPUOperationStatus result = cpu->VMemRead(esp + i, 4, &val); - if (result == CPUS_OP_OK) { - log_debug("%s %08x [esp%c%02x] = %08x%s\n", ((i == 0) ? "=>" : " "), esp + i, ((i < 0) ? '-' : '+'), ((i < 0) ? -i : i), val, ((esp + i) == ebp) ? " <= EBP" : ""); - } - else { - log_debug("%s %08x [esp%c%02x] = ........%s\n", ((i == 0) ? "=>" : " "), esp + i, ((i < 0) ? '-' : '+'), ((i < 0) ? -i : i), ((esp + i) == ebp) ? " <= EBP" : ""); - } - } - log_debug("\n"); -} - -void DumpCPUMemory(Cpu *cpu, uint32_t address, uint32_t size, bool physical) { - log_debug("%s memory at 0x%08x:\n", (physical ? "Physical" : "Virtual"), address); - char *mem = new char[size]; - if (physical) { - if (cpu->MemRead(address, size, mem)) { - log_debug("\n\n"); - delete[] mem; - return; - } - } - else { - if (cpu->VMemRead(address, size, mem)) { - log_debug("\n\n"); - delete[] mem; - return; - } - } - - for (uint32_t i = 0x00; i < size; i++) { - if ((i & 0xF) == 0x0) { - log_debug("%08x ", address + i); - } - if ((i & 0xF) == 0x8) { - log_debug(" "); - } - log_debug("%02x ", mem[i] & 0xFF); - if ((i & 0xF) == 0xF) { - log_debug("\n"); - } - } - if (size & 0xF) { log_debug("\n"); } - log_debug("\n"); - - delete[] mem; -} - -void DumpCPUDisassembly(Cpu* cpu, uint32_t address, uint32_t count, bool physical) { - log_debug("%s memory disassembly at 0x%08x:\n", (physical ? "Physical" : "Virtual"), address); - uint8_t mem[16]; - - ZydisDecoder decoder; - ZydisDecoderInit(&decoder, - ZYDIS_MACHINE_MODE_LEGACY_32, - ZYDIS_ADDRESS_WIDTH_32); - - ZydisFormatter formatter; - ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL); - - ZydisDecodedInstruction instruction; - - for (uint32_t i = 0; i < count; i++) { - if (physical) { - if (cpu->MemRead(address, 16, mem)) { - log_debug("\n\n"); - return; - } - } - else { - if (cpu->VMemRead(address, 16, mem)) { - log_debug("\n\n"); - return; - } - } - - auto result = ZydisDecoderDecodeBuffer(&decoder, mem, 16, address, &instruction); - if (ZYDIS_SUCCESS(result)) { - char buffer[256]; - ZydisFormatterFormatInstruction(&formatter, &instruction, buffer, sizeof(buffer)); - log_debug("%08x %s\n", address, buffer); - } - address += instruction.length; - } -} - -} diff --git a/src/core/vixen/debug.h b/src/core/vixen/debug.h deleted file mode 100644 index 559779a..0000000 --- a/src/core/vixen/debug.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "vixen/cpu.h" -#include "vixen/log.h" - -namespace vixen { - -using namespace vixen::cpu; - -/*! - * Print the CPU registers - */ -void DumpCPURegisters(Cpu *cpu); - -/*! - * Dump CPU stack - */ -void DumpCPUStack(Cpu *cpu, int32_t offsetStart = -0x20, int32_t offsetEnd = 0x10); - -/*! - * Dump memory - */ -void DumpCPUMemory(Cpu *cpu, uint32_t address, uint32_t size, bool physical); - -/*! - * Disassemble memory region - */ -void DumpCPUDisassembly(Cpu *cpu, uint32_t address, uint32_t size, bool physical); - -} diff --git a/src/core/vixen/dev.cpp b/src/core/vixen/dev.cpp deleted file mode 100644 index b3921b7..0000000 --- a/src/core/vixen/dev.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include -#include "dev.h" - -namespace vixen { - -/*! - * Constructor - */ -Device::Device(MemoryRegion *mem) -{ -} - -} diff --git a/src/core/vixen/dev.h b/src/core/vixen/dev.h deleted file mode 100644 index 0db7b6c..0000000 --- a/src/core/vixen/dev.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "vixen/memregion.h" - -namespace vixen { - -/*! - * Device base class - */ -class Device { -protected: -public: - Device(MemoryRegion *mem); -}; - -} diff --git a/src/core/vixen/emulator.h b/src/core/vixen/emulator.h deleted file mode 100644 index 43661ba..0000000 --- a/src/core/vixen/emulator.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -namespace vixen { - -/*! - * Interface for main emulator functions. - */ -class Emulator { -public: - virtual int RunCpu() = 0; - virtual void Stop() = 0; -}; - -} diff --git a/src/core/vixen/hw/CMakeLists.txt b/src/core/vixen/hw/CMakeLists.txt deleted file mode 100644 index fdef26c..0000000 --- a/src/core/vixen/hw/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -file(GLOB DIR_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/ata/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/ata/cmds/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/ata/drvs/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/atapi/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/atapi/cmds/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/basic/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/bus/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/sm/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/pci/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/pci/bmide/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/nv2a/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/ohci/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/xid/*.h - ) - -file(GLOB DIR_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/ata/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/ata/cmds/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/ata/drvs/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/atapi/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/atapi/cmds/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/basic/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/bus/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/sm/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/pci/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/pci/bmide/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/ohci/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/xid/*.cpp - ) - -if (WIN32) - add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/basic/win32") -endif (WIN32) - - -set(SOURCES ${SOURCES} - ${DIR_HEADERS} - ${DIR_SOURCES} - PARENT_SCOPE - ) diff --git a/src/core/vixen/hw/basic/char.cpp b/src/core/vixen/hw/basic/char.cpp deleted file mode 100644 index f28e087..0000000 --- a/src/core/vixen/hw/basic/char.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "char.h" - -namespace vixen { - - - -} diff --git a/src/core/vixen/hw/basic/win32/CMakeLists.txt b/src/core/vixen/hw/basic/win32/CMakeLists.txt deleted file mode 100644 index 9ab3420..0000000 --- a/src/core/vixen/hw/basic/win32/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -file(GLOB DIR_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/*.h - ) - -file(GLOB DIR_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp - ) - -set(SOURCES ${SOURCES} - ${DIR_HEADERS} - ${DIR_SOURCES} - PARENT_SCOPE - ) diff --git a/src/core/vixen/hw/sm/sm.cpp b/src/core/vixen/hw/sm/sm.cpp deleted file mode 100644 index 1256279..0000000 --- a/src/core/vixen/hw/sm/sm.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "sm.h" - -namespace vixen { - - - -} diff --git a/src/core/vixen/memregion.cpp b/src/core/vixen/memregion.cpp deleted file mode 100644 index fa3726b..0000000 --- a/src/core/vixen/memregion.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "vixen/memregion.h" -#include "vixen/alloc.h" - -namespace vixen { - -/*! - * Constructor - */ -MemoryRegion::MemoryRegion(enum MemoryRegionType type, uint32_t start, size_t size, void *data) { - m_parent = nullptr; - m_subregions = nullptr; - m_type = type; - m_start = start; - m_size = size; - m_data = data; - m_handler = nullptr; - m_handler_user = nullptr; -} - -/*! - * Destructor - */ -MemoryRegion::~MemoryRegion() { - vfree(m_data); -} - -/*! - * Given a relative offset, determine the absolute offset based on parents - */ -uint32_t MemoryRegion::GetAbsoluteAddress(uint32_t offset) { - uint32_t addr = m_start; - - for (MemoryRegion *p = m_parent; p != nullptr; p = p->m_parent) { - addr += p->m_start; - } - - return addr + offset; -} - -/*! - * Set the parent of this region - */ -void MemoryRegion::SetParent(MemoryRegion *parent) { - m_parent = parent; -} - -/*! - * Set the MMIO event handler for this region - */ -void MemoryRegion::SetEventHandler(MemoryRegionEventHandler handler, void *user_data) { - m_handler = handler; - m_handler_user = user_data; -} - -/*! - * Add a subregion to this region - */ -int MemoryRegion::AddSubRegion(MemoryRegion *region) { - m_subregions = new MemoryRegionLink{ region, m_subregions }; - region->SetParent(this); - return 0; -} - -} diff --git a/src/core/vixen/module.cpp b/src/core/vixen/module.cpp deleted file mode 100644 index 4e55089..0000000 --- a/src/core/vixen/module.cpp +++ /dev/null @@ -1,138 +0,0 @@ -#include "vixen/util.h" -#include "vixen/log.h" -#include "vixen/module.h" - -#include "vixen/cpu_module.h" - -namespace vixen { - -#ifdef _WIN32 -static const ci_wstring kLibraryPathSuffix = L".dll"; -#else -static const ci_wstring kLibraryPathSuffix = L".so"; -#endif - - -void ModuleRepository::Enumerate(std::wstring modulePath) { - using namespace std::experimental::filesystem; - path pPath(absolute(modulePath)); - - log_debug("Enumerating modules in %S\n", pPath.wstring().c_str()); - - // Clear list of modules - m_cpuModules.clear(); - - // Open every shared library in the modules path and its subdirectories - for (recursive_directory_iterator next(pPath), end; next != end; ++next) { - auto entry = next->path(); - auto wsEntry = entry.wstring(); - ci_wstring filename = ci_wstring(entry.filename().wstring().c_str()); - - // Found a shared library - if (!is_directory(entry) && ends_with(filename, kLibraryPathSuffix)) { - SharedLibrary *library; - auto status = SharedLibrary_Load(entry.wstring(), &library); - - // Failed to load the library - if (status != kLibraryLoadSuccess) { - log_debug("Failed to load module: %S\n", filename.c_str()); - continue; - } - - // Retrieve CPU module info - auto moduleInfo = (vixen::modules::Info *)library->GetExport("vxnModuleInfo"); - if (moduleInfo == nullptr) { - delete library; - continue; - } - - // Check if module API version matches - if (moduleInfo->apiVersion != vixen::modules::apiVersion) { - log_debug("%S: Module API version mismatch: expected %d, found %d\n", wsEntry.c_str(), vixen::modules::apiVersion, moduleInfo->apiVersion); - delete library; - continue; - } - - // Handle each specific type of module - switch (moduleInfo->type) { - case vixen::modules::TYPE_CPU: { - vixen::modules::cpu::Info *cpuModuleInfo = (vixen::modules::cpu::Info *)moduleInfo; - - // Check if the CPU module API version matches - if (cpuModuleInfo->cpuModuleAPIVersion == vixen::modules::cpu::apiVersion) { - // Fill in module data and add it to the list - CPUModuleInfo info = { - wsEntry.c_str(), - cpuModuleInfo->moduleName, - cpuModuleInfo->moduleVersion - }; - m_cpuModules.push_back(info); - log_debug("Found %s %s in %S\n", info.moduleName.c_str(), info.moduleVersion.c_str(), wsEntry.c_str()); - - // Retrieve CPU module capabilities - auto moduleCaps = (vixen::modules::cpu::Capabilities *)library->GetExport("vxnModuleCaps"); - if (moduleCaps != nullptr) { - log_debug("Capabilities:\n"); - log_debug(" Guest debugging: %s\n", ((moduleCaps->guestDebugging) ? "yes" : "no")); - } - } - else { - log_debug("%S: CPU module API version mismatch: expected %d, found %d\n", wsEntry.c_str(), vixen::modules::cpu::apiVersion, cpuModuleInfo->cpuModuleAPIVersion); - } - break; - } - default: { - log_debug("%S: Unknown module type %d\n", wsEntry.c_str()); - break; - } - } - - delete library; - } - } -} - -ModuleLoadStatus LoadCPUModule(std::wstring libraryPath, CPUModuleInstance *instance) { - SharedLibrary *library; - auto status = SharedLibrary_Load(libraryPath, &library); - if (status != kLibraryLoadSuccess) { - return kModuleLibraryLoadFailed; - } - - auto moduleInfo = (vixen::modules::Info *)library->GetExport("vxnModuleInfo"); - if (moduleInfo == nullptr) { - delete library; - return kModuleInvalidLibrary; - } - - if (moduleInfo->type != vixen::modules::TYPE_CPU) { - delete library; - return kModuleInvalidType; - } - - auto cpuModuleInfo = (vixen::modules::cpu::Info *)moduleInfo; - - if ((moduleInfo->apiVersion != vixen::modules::apiVersion) || - (cpuModuleInfo->cpuModuleAPIVersion != vixen::modules::cpu::apiVersion)) { - delete library; - return kModuleLoadAPIVersionMismatch; - } - - vixen::modules::cpu::ICPUModule *moduleInstance = cpuModuleInfo->createModule(); - if (moduleInstance == nullptr) { - delete library; - return kModuleInstantiationFailed; - } - - instance->library = library; - instance->cpuModule = moduleInstance; - return kModuleLoadSuccess; -} - -CPUModuleInstance::~CPUModuleInstance() { - cpuModule->Cleanup(); - delete library; -} - -} - diff --git a/src/core/vixen/module.h b/src/core/vixen/module.h deleted file mode 100644 index 71264ce..0000000 --- a/src/core/vixen/module.h +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "vixen/cpu_module.h" -#include "vixen/shlibrary.h" - -namespace vixen { - -// ----- Module load status --------------------------------------------------- - -/*! - * Indicates the result of attempting to load a module. - */ -typedef int32_t ModuleLoadStatus; - - -// The module was loaded successfully -const ModuleLoadStatus kModuleLoadSuccess = 0; - -// The module could not be loaded because of a version mismatch -const ModuleLoadStatus kModuleLoadAPIVersionMismatch = 0x80000001; - -// The module instantiation failed -const ModuleLoadStatus kModuleInstantiationFailed = 0x80000002; - -// The module library failed to be loaded -const ModuleLoadStatus kModuleLibraryLoadFailed = 0xF0000001; - -// The loaded library does not expose a valid module interface -const ModuleLoadStatus kModuleInvalidLibrary = 0xF0000002; - -// The module type does not match the expected type -const ModuleLoadStatus kModuleInvalidType = 0xF0000003; - -// ----- Basic module functions ----------------------------------------------- - -struct CPUModuleInstance { - SharedLibrary *library; - vixen::modules::cpu::ICPUModule *cpuModule; - ~CPUModuleInstance(); -}; - -/*! - * Loads a CPU module from the supplied library into the specified instance. - */ -ModuleLoadStatus LoadCPUModule(std::wstring libraryPath, CPUModuleInstance *instance); - -// ----- Module information --------------------------------------------------- - -struct CPUModuleInfo { - std::wstring libraryPath; - std::string moduleName; - std::string moduleVersion; -}; - -// ----- Module repository ---------------------------------------------------- - -/*! - * A repository of viXen modules. - */ -class ModuleRepository { -public: - /*! - * Populates the module repository by enumerating modules in the specified - * path. By default it looks in the modules folder and its subdirectories. - */ - void Enumerate(std::wstring path = L"modules"); - - std::vector& GetCPUModules() { return m_cpuModules; } -private: - std::vector m_cpuModules; -}; - -} - diff --git a/src/core/vixen/util/CMakeLists.txt b/src/core/vixen/util/CMakeLists.txt deleted file mode 100644 index 9ab3420..0000000 --- a/src/core/vixen/util/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -file(GLOB DIR_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/*.h - ) - -file(GLOB DIR_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp - ) - -set(SOURCES ${SOURCES} - ${DIR_HEADERS} - ${DIR_SOURCES} - PARENT_SCOPE - ) diff --git a/src/core/vixen/util/fifo.cpp b/src/core/vixen/util/fifo.cpp deleted file mode 100644 index a113f61..0000000 --- a/src/core/vixen/util/fifo.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "fifo.h" - -namespace vixen { - - - -} diff --git a/src/core/vixen/xbe.cpp b/src/core/vixen/xbe.cpp deleted file mode 100644 index 10ef388..0000000 --- a/src/core/vixen/xbe.cpp +++ /dev/null @@ -1,873 +0,0 @@ -// ****************************************************************** -// * -// * .,-::::: .,:: .::::::::. .,:: .: -// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; -// * [[[ '[[,,[[' [[[__[[\. '[[,,[[' -// * $$$ Y$$$P $$""""Y$$ Y$$$P -// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, -// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, -// * -// * Cxbx->Core->Xbe.cpp -// * -// * This file is part of the Cxbx project. -// * -// * Cxbx and Cxbe are free software; you can redistribute them -// * and/or modify them under the terms of the GNU General Public -// * License as published by the Free Software Foundation; either -// * version 2 of the license, or (at your option) any later version. -// * -// * This program is distributed in the hope that it will be useful, -// * but WITHOUT ANY WARRANTY; without even the implied warranty of -// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// * GNU General Public License for more details. -// * -// * You should have recieved a copy of the GNU General Public License -// * along with this program; see the file COPYING. -// * If not, write to the Free Software Foundation, Inc., -// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. -// * -// * (c) 2002-2003 Aaron Robinson -// * -// * All rights reserved -// * -// ****************************************************************** - -#include -#include -#include -#include -#include - -#include "xbe.h" - -namespace vixen { - -uint32 RoundUp(uint32 dwValue, uint32 dwMult) -{ - if(dwMult == 0) - return dwValue; - - return dwValue - (dwValue-1)%dwMult + (dwMult - 1); -} - -// clear the current error (returns false if error was fatal) -bool Error::ClearError() -{ - if(m_bFatal) - return false; - - delete[] m_szError; - - m_szError = 0; - - m_bFatal = false; - - return true; -} - -// protected so only derived class may set an error -void Error::SetError(const char *x_szError, bool x_bFatal) -{ - if(m_szError == 0) - m_szError = new char[256]; - - strncpy(m_szError, x_szError, 255); - - m_bFatal = x_bFatal; - - return; -} - - -// construct via Xbe file -Xbe::Xbe(const char *x_szFilename) -{ - char szBuffer[260]; - - ConstructorInit(); - - printf("Xbe::Xbe: Opening Xbe file..."); - - FILE *XbeFile = fopen(x_szFilename, "rb"); - - // verify Xbe file was opened successfully - if(XbeFile == 0) - { - SetError("Could not open Xbe file.", true); - return; - } - - printf("OK\n"); - - // remember the Xbe path - { - printf("Xbe::Xbe: Storing Xbe Path..."); - - strcpy(m_szPath, x_szFilename); - - int v=0, c=0; - - while(m_szPath[v] != '\0') - { - if(m_szPath[v] == '\\') - c = v+1; - v++; - } - - m_szPath[c] = '\0'; - } - - printf("OK\n"); - - // read Xbe image header - { - printf("Xbe::Xbe: Reading Image Header..."); - - if(fread(&m_Header, sizeof(m_Header), 1, XbeFile) != 1) - { - SetError("Unexpected end of file while reading Xbe Image Header", true); - goto cleanup; - } - - if(m_Header.dwMagic != *(uint32 *)"XBEH") - { - SetError("Invalid magic number in Xbe file", true); - goto cleanup; - } - - printf("OK\n"); - } - - // read Xbe image header extra bytes - if(m_Header.dwSizeofHeaders > sizeof(m_Header)) - { - printf("Xbe::Xbe: Reading Image Header Extra Bytes..."); - - uint32 ExSize = RoundUp(m_Header.dwSizeofHeaders, 0x1000) - sizeof(m_Header); - - m_HeaderEx = new char[ExSize]; - - if(fread(m_HeaderEx, ExSize, 1, XbeFile) != 1) - { - SetError("Unexpected end of file while reading Xbe Image Header (Ex)", true); - goto cleanup; - } - - printf("OK\n"); - } - - // read Xbe certificate - { - printf("Xbe::Xbe: Reading Certificate..."); - - fseek(XbeFile, m_Header.dwCertificateAddr - m_Header.dwBaseAddr, SEEK_SET); - - if(fread(&m_Certificate, sizeof(m_Certificate), 1, XbeFile) != 1) - { - SetError("Unexpected end of file while reading Xbe Certificate", true); - goto cleanup; - } - - setlocale( LC_ALL, "English" ); - - //wcstombs(m_szAsciiTitle, m_Certificate.wszTitleName, 40); - char *c = m_szAsciiTitle; - char *d = (char *) m_Certificate.wszTitleName; - while (*d) { - *c++ = *d++; - d++; - } - *c = 0; - - printf("OK\n"); - - printf("Xbe::Xbe: Title identified as %s\n", m_szAsciiTitle); - } - - // read Xbe section headers - { - printf("Xbe::Xbe: Reading Section Headers...\n"); - - fseek(XbeFile, m_Header.dwSectionHeadersAddr - m_Header.dwBaseAddr, SEEK_SET); - - m_SectionHeader = new SectionHeader[m_Header.dwSections]; - - for(uint32 v=0;v %s\n", GetError()); - } - - fclose(XbeFile); - - return; -} - -// deconstructor -Xbe::~Xbe() -{ - if(m_bzSection != 0) - { - for(uint32 v=0;v"); - for(int y=0;y<16;y++) - { - fprintf(x_file, "\n "); - for(int x=0;x<16;x++) - fprintf(x_file, "%.02X", m_Header.pbDigitalSignature[y*16+x]); - } - fprintf(x_file, "\n \n"); - } - - fprintf(x_file, "Base Address : 0x%.08X\n", m_Header.dwBaseAddr); - fprintf(x_file, "Size of Headers : 0x%.08X\n", m_Header.dwSizeofHeaders); - fprintf(x_file, "Size of Image : 0x%.08X\n", m_Header.dwSizeofImage); - fprintf(x_file, "Size of Image Header : 0x%.08X\n", m_Header.dwSizeofImageHeader); - fprintf(x_file, "TimeDate Stamp : 0x%.08X (%s)\n", m_Header.dwTimeDate, BetterTime(ctime((const time_t*)&m_Header.dwTimeDate))); - fprintf(x_file, "Certificate Address : 0x%.08X\n", m_Header.dwCertificateAddr); - fprintf(x_file, "Number of Sections : 0x%.08X\n", m_Header.dwSections); - fprintf(x_file, "Section Headers Address : 0x%.08X\n", m_Header.dwSectionHeadersAddr); - - // print init flags - { - fprintf(x_file, "Init Flags : 0x%.08X ", *(uint32*)&m_Header.dwInitFlags); - - if(m_Header.dwInitFlags.bMountUtilityDrive) - fprintf(x_file, "[Mount Utility Drive] "); - - if(m_Header.dwInitFlags.bFormatUtilityDrive) - fprintf(x_file, "[Format Utility Drive] "); - - if(m_Header.dwInitFlags.bLimit64MB) - fprintf(x_file, "[Limit Devkit Run Time Memory to 64MB] "); - - if(!m_Header.dwInitFlags.bDontSetupHarddisk) - fprintf(x_file, "[Setup Harddisk] "); - - fprintf(x_file, "\n"); - } - - char AsciiFilename[40]; - - setlocale( LC_ALL, "English" ); - - char *wszFilename = (char *)GetAddr(m_Header.dwDebugUnicodeFilenameAddr); - - if(wszFilename != NULL) { - //wcstombs(AsciiFilename, wszFilename, 40); - char *c = wszFilename; - char *d = AsciiFilename; - while (*c) { - *d++ = *c++; - c++; - } - } else { - AsciiFilename[0] = '\0'; - } - - fprintf(x_file, "Entry Point : 0x%.08X (Retail: 0x%.08X, Debug: 0x%.08X)\n", m_Header.dwEntryAddr, m_Header.dwEntryAddr ^ XOR_EP_RETAIL, m_Header.dwEntryAddr ^ XOR_EP_DEBUG); - fprintf(x_file, "TLS Address : 0x%.08X\n", m_Header.dwTLSAddr); - fprintf(x_file, "(PE) Stack Commit : 0x%.08X\n", m_Header.dwPeStackCommit); - fprintf(x_file, "(PE) Heap Reserve : 0x%.08X\n", m_Header.dwPeHeapReserve); - fprintf(x_file, "(PE) Heap Commit : 0x%.08X\n", m_Header.dwPeHeapCommit); - fprintf(x_file, "(PE) Base Address : 0x%.08X\n", m_Header.dwPeBaseAddr); - fprintf(x_file, "(PE) Size of Image : 0x%.08X\n", m_Header.dwPeSizeofImage); - fprintf(x_file, "(PE) Checksum : 0x%.08X\n", m_Header.dwPeChecksum); - fprintf(x_file, "(PE) TimeDate Stamp : 0x%.08X (%s)\n", m_Header.dwPeTimeDate, BetterTime(ctime((time_t*)&m_Header.dwPeTimeDate))); - fprintf(x_file, "Debug Pathname Address : 0x%.08X (\"%s\")\n", m_Header.dwDebugPathnameAddr, GetAddr(m_Header.dwDebugPathnameAddr)); - fprintf(x_file, "Debug Filename Address : 0x%.08X (\"%s\")\n", m_Header.dwDebugFilenameAddr, GetAddr(m_Header.dwDebugFilenameAddr)); - fprintf(x_file, "Debug Unicode filename Address : 0x%.08X (L\"%s\")\n", m_Header.dwDebugUnicodeFilenameAddr, AsciiFilename); - fprintf(x_file, "Kernel Image Thunk Address : 0x%.08X (Retail: 0x%.08X, Debug: 0x%.08X)\n", m_Header.dwKernelImageThunkAddr, m_Header.dwKernelImageThunkAddr ^ XOR_KT_RETAIL, m_Header.dwKernelImageThunkAddr ^ XOR_KT_DEBUG); - fprintf(x_file, "NonKernel Import Dir Address : 0x%.08X\n", m_Header.dwNonKernelImportDirAddr); - fprintf(x_file, "Library Versions : 0x%.08X\n", m_Header.dwLibraryVersions); - fprintf(x_file, "Library Versions Address : 0x%.08X\n", m_Header.dwLibraryVersionsAddr); - fprintf(x_file, "Kernel Library Version Address : 0x%.08X\n", m_Header.dwKernelLibraryVersionAddr); - fprintf(x_file, "XAPI Library Version Address : 0x%.08X\n", m_Header.dwXAPILibraryVersionAddr); - fprintf(x_file, "Logo Bitmap Address : 0x%.08X\n", m_Header.dwLogoBitmapAddr); - fprintf(x_file, "Logo Bitmap Size : 0x%.08X\n", m_Header.dwSizeofLogoBitmap); - fprintf(x_file, "\n"); - fprintf(x_file, "Dumping XBE Certificate...\n"); - fprintf(x_file, "\n"); - fprintf(x_file, "Size of Certificate : 0x%.08X\n", m_Certificate.dwSize); - fprintf(x_file, "TimeDate Stamp : 0x%.08X (%s)\n", m_Certificate.dwTimeDate, BetterTime(ctime((time_t*)&m_Certificate.dwTimeDate))); - fprintf(x_file, "Title ID : 0x%.08X\n", m_Certificate.dwTitleId); - fprintf(x_file, "Title : L\"%s\"\n", m_szAsciiTitle); - - // print alternate title IDs - { - fprintf(x_file, "Alternate Titles IDs : "); - - for(int v=0;v<0x10;v++) - { - if(v != 0) - fprintf(x_file, " "); - fprintf(x_file, "0x%.08X", m_Certificate.dwAlternateTitleId[v]); - if(v != 0x0F) - fprintf(x_file, "\n"); - } - - fprintf(x_file, "\n"); - } - - fprintf(x_file, "Allowed Media : 0x%.08X\n", m_Certificate.dwAllowedMedia); - fprintf(x_file, "Game Region : 0x%.08X\n", m_Certificate.dwGameRegion); - fprintf(x_file, "Game Ratings : 0x%.08X\n", m_Certificate.dwGameRatings); - fprintf(x_file, "Disk Number : 0x%.08X\n", m_Certificate.dwDiskNumber); - fprintf(x_file, "Version : 0x%.08X\n", m_Certificate.dwVersion); - - // print LAN key - { - fprintf(x_file, "LAN Key : "); - for(int x=0;x<16;x++) - fprintf(x_file, "%.02X", m_Certificate.bzLanKey[x]); - fprintf(x_file, "\n"); - } - - // print signature key - { - fprintf(x_file, "Signature Key : "); - for(int x=0;x<16;x++) - fprintf(x_file, "%.02X", m_Certificate.bzSignatureKey[x]); - fprintf(x_file, "\n"); - } - - // print alternate signature keys - { - fprintf(x_file, "Title Alternate Signature Keys : "); - for(int y=0;y<16;y++) - { - fprintf(x_file, "\n "); - for(int x=0;x<16;x++) - fprintf(x_file, "%.02X", m_Certificate.bzTitleAlternateSignatureKey[y][x]); - } - fprintf(x_file, "\n \n"); - } - - fprintf(x_file, "\n"); - fprintf(x_file, "Dumping XBE Section Headers...\n"); - fprintf(x_file, "\n"); - - // print section headers - { - for(uint32 v=0;vdwDataStartAddr); - fprintf(x_file, "Data End Address : 0x%.08X\n", m_TLS->dwDataEndAddr); - fprintf(x_file, "TLS Index Address : 0x%.08X\n", m_TLS->dwTLSIndexAddr); - fprintf(x_file, "TLS Callback Address : 0x%.08X\n", m_TLS->dwTLSCallbackAddr); - fprintf(x_file, "Size of Zero Fill : 0x%.08X\n", m_TLS->dwSizeofZeroFill); - fprintf(x_file, "Characteristics : 0x%.08X\n", m_TLS->dwCharacteristics); - } - else - { - fprintf(x_file, "(This XBE contains no TLS)\n"); - } -} - - -// import logo bitmap from raw monochrome data -void Xbe::ImportLogoBitmap(const uint08 x_Gray[100*17]) -{ - char *LogoBuffer = new char[4*1024]; - uint32 LogoSize = 0; - - // encode logo bitmap - { - for(uint32 v=1;v<100*17;LogoSize++) - { - char color = x_Gray[v] >> 4; - - uint32 len = 1; - - while(++v<100*17-1 && len < 1024 && color == x_Gray[v] >> 4) - len++; - - LogoRLE *cur = (LogoRLE *)&LogoBuffer[LogoSize]; - - if(len <= 7) - { - cur->m_Eight.bType1 = 1; - cur->m_Eight.Len = len; - cur->m_Eight.Data = color; - } - else - { - cur->m_Sixteen.bType1 = 0; - cur->m_Sixteen.bType2 = 1; - cur->m_Sixteen.Len = len; - cur->m_Sixteen.Data = color; - LogoSize++; - } - } - } - - // check if there is room to save this, if not then throw an error - { - uint08 *RLE = GetLogoBitmap(LogoSize); - - if(RLE == 0) - { - if(GetError() == 0) - SetError("Logo bitmap could not be imported (not enough space in file?)", false); - - return; - } - - memcpy(RLE, LogoBuffer, LogoSize); - } - - return; -} - -// ****************************************************************** -// * ExportLogoBitmap -// ****************************************************************** -// * -// * This algorithm was originally discovered by superfro. I couldnt -// * figure out what the hell the encoding format was before he gave -// * me the information: -// * -// * basically what is going on here is a single pass through the -// * bitmap data, with 2 possible encodings per rle chunk. data is -// * stored as 4 bit grayscale, so the logical approach is to expand -// * this to 8 bit using a simple 4 bit left shift (*16). However, it -// * has been suggested to me by superfro that you might calculate a -// * slightly darker image by multiplying by 15 and adding .5. It's -// * a toss up, but i've choosen a simple bit shift left. -// * -// ****************************************************************** -void Xbe::ExportLogoBitmap(uint08 x_Gray[100*17]) -{ - memset(x_Gray, 0, 100*17); - - uint32 dwLength = m_Header.dwSizeofLogoBitmap; - - uint08 *RLE = GetAddr(m_Header.dwLogoBitmapAddr); - - if(RLE == 0 || GetError()) - return; - - uint32 o = 0; - - for(uint32 v=0;vm_Eight.bType1) - { - len = cur->m_Eight.Len; - data = cur->m_Eight.Data; - } - else - { - if(cur->m_Sixteen.bType2) - { - len = cur->m_Sixteen.Len; - data = cur->m_Sixteen.Data; - v += 1; - } - } - - for(uint32 j=0;j= VirtAddr) && (x_dwVirtualAddress < (VirtAddr + VirtSize)) ) - return &m_bzSection[v][x_dwVirtualAddress - VirtAddr]; - } - } - - return 0; -} - -// return a modifiable pointer to logo bitmap data -uint08 *Xbe::GetLogoBitmap(uint32 x_dwSize) -{ - uint32 dwOffs = m_Header.dwLogoBitmapAddr - m_Header.dwBaseAddr; - uint32 dwLength = m_Header.dwSizeofLogoBitmap; - - if(dwOffs == 0 || dwLength == 0) - return 0; - - // if this bitmap will fit inside the already existing one, we don't need to resize, just return pointer - if(dwLength >= x_dwSize) - { - // update size of headers, if necessary - if(dwOffs < m_Header.dwSizeofHeaders) - { - m_Header.dwSizeofHeaders -= dwLength; - m_Header.dwSizeofHeaders += x_dwSize; - m_Header.dwSizeofLogoBitmap = x_dwSize; - - return GetAddr(m_Header.dwLogoBitmapAddr); - } - } - - return 0; -} - -} diff --git a/src/core/vixen/xbe.h b/src/core/vixen/xbe.h deleted file mode 100644 index 75fd655..0000000 --- a/src/core/vixen/xbe.h +++ /dev/null @@ -1,382 +0,0 @@ -// ****************************************************************** -// * -// * .,-::::: .,:: .::::::::. .,:: .: -// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; -// * [[[ '[[,,[[' [[[__[[\. '[[,,[[' -// * $$$ Y$$$P $$""""Y$$ Y$$$P -// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, -// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, -// * -// * Cxbx->Core->Xbe.h -// * -// * This file is part of the Cxbx project. -// * -// * Cxbx and Cxbe are free software; you can redistribute them -// * and/or modify them under the terms of the GNU General Public -// * License as published by the Free Software Foundation; either -// * version 2 of the license, or (at your option) any later version. -// * -// * This program is distributed in the hope that it will be useful, -// * but WITHOUT ANY WARRANTY; without even the implied warranty of -// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// * GNU General Public License for more details. -// * -// * You should have recieved a copy of the GNU General Public License -// * along with this program; see the file COPYING. -// * If not, write to the Free Software Foundation, Inc., -// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. -// * -// * (c) 2002-2003 Aaron Robinson -// * -// * All rights reserved -// * -// ****************************************************************** -#pragma once - -#include -#include - -namespace vixen { - -// CxbxKrnl exports, others import -#ifndef _CXBXKRNL_INTERNAL -#define CXBXKRNL_API __declspec(dllimport) -#else -#define CXBXKRNL_API __declspec(dllexport) -#endif - -// Caustik's favorite typedefs -typedef signed int sint; -typedef unsigned int uint; -typedef int8_t int08; -typedef int16_t int16; -typedef int32_t int32; -typedef uint8_t uint08; -typedef uint16_t uint16; -typedef uint32_t uint32; -typedef int8_t sint08; -typedef int16_t sint16; -typedef int32_t sint32; - -// define this to track resources for debugging purposes -//#define _DEBUG_TRACK_VB // Vertex Buffers -//#define _DEBUG_TRACK_VS // Vertex Shaders -//#define _DEBUG_TRACK_PB // Push Buffers - -// define this to track memory allocations -//#define _DEBUG_ALLOC - -// define this to trace intercepted function calls -#define _DEBUG_TRACE - -// define this to trace warnings -#define _DEBUG_WARNINGS - -// define these to dump textures -//#define _DEBUG_DUMP_TEXTURE_SETTEXTURE "C:\\Aaron\\Textures\\" -//#define _DEBUG_DUMP_TEXTURE_REGISTER "C:\\Aaron\\Textures\\" - -// version information -#ifndef _DEBUG_TRACE -#define _CXBX_VERSION "0.8.0-Pre3" -#else -#define _CXBX_VERSION "0.8.0-Pre3-Trace" -#endif - -// round dwValue to the nearest multiple of dwMult -uint32 RoundUp(uint32 dwValue, uint32 dwMult); - -// debug mode choices, either console screen or external file -enum DebugMode -{ - DM_NONE, - DM_CONSOLE, - DM_FILE -}; - -// maximum number of threads cxbx can handle -#define MAXIMUM_XBOX_THREADS 256 - -extern volatile bool g_bPrintfOn; - -// convienance debug output macros -#ifdef _DEBUG_TRACE -#define DbgPrintf if(g_bPrintfOn) printf -#else -inline void null_func(...) { } -#define DbgPrintf null_func -#endif - -// inherit from this class for handy error reporting capability -class Error -{ - public: - // return current error (zero if there is none) - const char *GetError() const { return m_szError; } - - // is the current error fatal? (class is "dead" on fatal errors) - bool IsFatal() const { return m_bFatal; } - - // clear the current error (returns false if error was fatal) - bool ClearError(); - - protected: - // protected constructor so this class must be inherited from - Error() : m_bFatal(false), m_szError(0) { } - - // protected deconstructor - ~Error() { delete[] m_szError; } - - // protected so only derived class may set an error - void SetError(const char *x_szError, bool x_bFatal); - - private: - // current error information - bool m_bFatal; - char *m_szError; -}; - -// Xbe (Xbox Executable) file object -class Xbe : public Error -{ - public: - // construct via Xbe file - Xbe(const char *x_szFilename); - - // deconstructor - ~Xbe(); - - // dump Xbe information to text file - void DumpInformation(FILE *x_file); - - // import logo bitmap from raw monochrome data - void ImportLogoBitmap(const uint08 x_Gray[100*17]); - - // export logo bitmap to raw monochrome data - void ExportLogoBitmap(uint08 x_Gray[100*17]); - - // Xbe header - #pragma pack(push, 1) - struct Header - { - uint32 dwMagic; // 0x0000 - magic number [should be "XBEH"] - uint08 pbDigitalSignature[256]; // 0x0004 - digital signature - uint32 dwBaseAddr; // 0x0104 - base address - uint32 dwSizeofHeaders; // 0x0108 - size of headers - uint32 dwSizeofImage; // 0x010C - size of image - uint32 dwSizeofImageHeader; // 0x0110 - size of image header - uint32 dwTimeDate; // 0x0114 - timedate stamp - uint32 dwCertificateAddr; // 0x0118 - certificate address - uint32 dwSections; // 0x011C - number of sections - uint32 dwSectionHeadersAddr; // 0x0120 - section headers address - - struct InitFlags // 0x0124 - initialization flags - { - uint32 bMountUtilityDrive : 1; // mount utility drive flag - uint32 bFormatUtilityDrive : 1; // format utility drive flag - uint32 bLimit64MB : 1; // limit development kit run time memory to 64mb flag - uint32 bDontSetupHarddisk : 1; // don't setup hard disk flag - uint32 Unused : 4; // unused (or unknown) - uint32 Unused_b1 : 8; // unused (or unknown) - uint32 Unused_b2 : 8; // unused (or unknown) - uint32 Unused_b3 : 8; // unused (or unknown) - } - dwInitFlags; - - uint32 dwEntryAddr; // 0x0128 - entry point address - uint32 dwTLSAddr; // 0x012C - thread local storage directory address - uint32 dwPeStackCommit; // 0x0130 - size of stack commit - uint32 dwPeHeapReserve; // 0x0134 - size of heap reserve - uint32 dwPeHeapCommit; // 0x0138 - size of heap commit - uint32 dwPeBaseAddr; // 0x013C - original base address - uint32 dwPeSizeofImage; // 0x0140 - size of original image - uint32 dwPeChecksum; // 0x0144 - original checksum - uint32 dwPeTimeDate; // 0x0148 - original timedate stamp - uint32 dwDebugPathnameAddr; // 0x014C - debug pathname address - uint32 dwDebugFilenameAddr; // 0x0150 - debug filename address - uint32 dwDebugUnicodeFilenameAddr; // 0x0154 - debug unicode filename address - uint32 dwKernelImageThunkAddr; // 0x0158 - kernel image thunk address - uint32 dwNonKernelImportDirAddr; // 0x015C - non kernel import directory address - uint32 dwLibraryVersions; // 0x0160 - number of library versions - uint32 dwLibraryVersionsAddr; // 0x0164 - library versions address - uint32 dwKernelLibraryVersionAddr; // 0x0168 - kernel library version address - uint32 dwXAPILibraryVersionAddr; // 0x016C - xapi library version address - uint32 dwLogoBitmapAddr; // 0x0170 - logo bitmap address - uint32 dwSizeofLogoBitmap; // 0x0174 - logo bitmap size - } - m_Header; - #pragma pack(pop) - - // Xbe header extra byte (used to preserve unknown data) - char *m_HeaderEx; - - // Xbe certificate - #pragma pack(push, 1) - struct Certificate - { - uint32 dwSize; // 0x0000 - size of certificate - uint32 dwTimeDate; // 0x0004 - timedate stamp - uint32 dwTitleId; // 0x0008 - title id - uint16 wszTitleName[40]; // 0x000C - title name (unicode) - uint32 dwAlternateTitleId[0x10]; // 0x005C - alternate title ids - uint32 dwAllowedMedia; // 0x009C - allowed media types - uint32 dwGameRegion; // 0x00A0 - game region - uint32 dwGameRatings; // 0x00A4 - game ratings - uint32 dwDiskNumber; // 0x00A8 - disk number - uint32 dwVersion; // 0x00AC - version - uint08 bzLanKey[16]; // 0x00B0 - lan key - uint08 bzSignatureKey[16]; // 0x00C0 - signature key - uint08 bzTitleAlternateSignatureKey[16][16]; // 0x00D0 - alternate signature keys - } - m_Certificate; - #pragma pack(pop) - - // Xbe section header - #pragma pack(push, 1) - struct SectionHeader - { - struct _Flags - { - uint32 bWritable : 1; // writable flag - uint32 bPreload : 1; // preload flag - uint32 bExecutable : 1; // executable flag - uint32 bInsertedFile : 1; // inserted file flag - uint32 bHeadPageRO : 1; // head page read only flag - uint32 bTailPageRO : 1; // tail page read only flag - uint32 Unused_a1 : 1; // unused (or unknown) - uint32 Unused_a2 : 1; // unused (or unknown) - uint32 Unused_b1 : 8; // unused (or unknown) - uint32 Unused_b2 : 8; // unused (or unknown) - uint32 Unused_b3 : 8; // unused (or unknown) - } - dwFlags; - - uint32 dwVirtualAddr; // virtual address - uint32 dwVirtualSize; // virtual size - uint32 dwRawAddr; // file offset to raw data - uint32 dwSizeofRaw; // size of raw data - uint32 dwSectionNameAddr; // section name addr - uint32 dwSectionRefCount; // section reference count - uint32 dwHeadSharedRefCountAddr; // head shared page reference count address - uint32 dwTailSharedRefCountAddr; // tail shared page reference count address - uint08 bzSectionDigest[20]; // section digest - } - *m_SectionHeader; - #pragma pack(pop) - - // Xbe library versions - #pragma pack(push, 1) - struct LibraryVersion - { - char szName[8]; // library name - uint16 wMajorVersion; // major version - uint16 wMinorVersion; // minor version - uint16 wBuildVersion; // build version - - struct Flags - { - uint16 QFEVersion : 13; // QFE Version - uint16 Approved : 2; // Approved? (0:no, 1:possibly, 2:yes) - uint16 bDebugBuild : 1; // Is this a debug build? - } - dwFlags; - } - *m_LibraryVersion, *m_KernelLibraryVersion, *m_XAPILibraryVersion; - #pragma pack(pop) - - // Xbe thread local storage - #pragma pack(push, 1) - struct TLS - { - uint32 dwDataStartAddr; // raw start address - uint32 dwDataEndAddr; // raw end address - uint32 dwTLSIndexAddr; // tls index address - uint32 dwTLSCallbackAddr; // tls callback address - uint32 dwSizeofZeroFill; // size of zero fill - uint32 dwCharacteristics; // characteristics - } - *m_TLS; - #pragma pack(pop) - - // Xbe section names, each 8 bytes max and null terminated - char (*m_szSectionName)[9]; - - // Xbe sections - uint08 **m_bzSection; - - // Xbe original path - char m_szPath[260]; - - // Xbe ascii title, translated from certificate title - char m_szAsciiTitle[40]; - - // retrieve thread local storage data address - uint08 *GetTLSData() { if(m_TLS == 0) return 0; else return GetAddr(m_TLS->dwDataStartAddr); } - - // retrieve thread local storage index address - uint32 *GetTLSIndex() { if(m_TLS == 0) return 0; else return (uint32*)GetAddr(m_TLS->dwTLSIndexAddr); } - - private: - // constructor initialization - void ConstructorInit(); - - // return a modifiable pointer inside this structure that corresponds to a virtual address - uint08 *GetAddr(uint32 x_dwVirtualAddress); - - // return a modifiable pointer to logo bitmap data - uint08 *GetLogoBitmap(uint32 x_dwSize); - - // used to encode/decode logo bitmap data - union LogoRLE - { - struct Eight - { - uint32 bType1 : 1; - uint32 Len : 3; - uint32 Data : 4; - } - m_Eight; - - struct Sixteen - { - uint32 bType1 : 1; - uint32 bType2 : 1; - uint32 Len : 10; - uint32 Data : 4; - } - m_Sixteen; - }; -}; - -// debug/retail XOR keys -const uint32 XOR_EP_DEBUG = 0x94859D4B; // Entry Point (Debug) -const uint32 XOR_EP_RETAIL = 0xA8FC57AB; // Entry Point (Retail) -const uint32 XOR_KT_DEBUG = 0xEFB1F152; // Kernel Thunk (Debug) -const uint32 XOR_KT_RETAIL = 0x5B6D40B6; // Kernel Thunk (Retail) - -// game region flags for Xbe certificate -const uint32 XBEIMAGE_GAME_REGION_NA = 0x00000001; -const uint32 XBEIMAGE_GAME_REGION_JAPAN = 0x00000002; -const uint32 XBEIMAGE_GAME_REGION_RESTOFWORLD = 0x00000004; -const uint32 XBEIMAGE_GAME_REGION_MANUFACTURING = 0x80000000; - -// media type flags for Xbe certificate -const uint32 XBEIMAGE_MEDIA_TYPE_HARD_DISK = 0x00000001; -const uint32 XBEIMAGE_MEDIA_TYPE_DVD_X2 = 0x00000002; -const uint32 XBEIMAGE_MEDIA_TYPE_DVD_CD = 0x00000004; -const uint32 XBEIMAGE_MEDIA_TYPE_CD = 0x00000008; -const uint32 XBEIMAGE_MEDIA_TYPE_DVD_5_RO = 0x00000010; -const uint32 XBEIMAGE_MEDIA_TYPE_DVD_9_RO = 0x00000020; -const uint32 XBEIMAGE_MEDIA_TYPE_DVD_5_RW = 0x00000040; -const uint32 XBEIMAGE_MEDIA_TYPE_DVD_9_RW = 0x00000080; -const uint32 XBEIMAGE_MEDIA_TYPE_DONGLE = 0x00000100; -const uint32 XBEIMAGE_MEDIA_TYPE_MEDIA_BOARD = 0x00000200; -const uint32 XBEIMAGE_MEDIA_TYPE_NONSECURE_HARD_DISK = 0x40000000; -const uint32 XBEIMAGE_MEDIA_TYPE_NONSECURE_MODE = 0x80000000; -const uint32 XBEIMAGE_MEDIA_TYPE_MEDIA_MASK = 0x00FFFFFF; - -// OpenXDK logo bitmap (used by cxbe by default) -extern uint08 OpenXDK[]; -extern uint32 dwSizeOfOpenXDK; - -} diff --git a/src/cpu-module-haxm/CMakeLists.txt b/src/cpu-module-haxm/CMakeLists.txt deleted file mode 100644 index 72b70ba..0000000 --- a/src/cpu-module-haxm/CMakeLists.txt +++ /dev/null @@ -1,48 +0,0 @@ -# Add sources -file(GLOB DIR_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/haxm/*.h - ) - -file(GLOB DIR_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/haxm/*.cpp - ) - -set(SOURCES ${SOURCES} - ${DIR_HEADERS} - ${DIR_SOURCES} - ) - - -# Export module -add_definitions(-DMODULE_EXPORTS) - -# Add Visual Studio filters to better organize the code -vs_set_filters("${SOURCES}") - -# Main Executable -if(NOT MSVC) - add_definitions("-Wall -Werror -O0 -g") -endif() -add_library(cpu-module-haxm SHARED "${SOURCES}") -target_include_directories(cpu-module-haxm PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - -# Include common module code -target_link_libraries(cpu-module-haxm common cpu-module) - -# Make the Debug and RelWithDebInfo targets use Program Database for Edit and Continue for easier debugging -vs_use_edit_and_continue() - -# Copy DLL to CLI output directory -string(TOLOWER ${CPU_MODULE} CPU_MODULE_LC) -if(CPU_MODULE_LC STREQUAL haxm) - if(MSVC) - add_custom_command(TARGET cpu-module-haxm - POST_BUILD - COMMAND if not exist \"$(ProjectDir)..\\cli\\$(Configuration)\\modules\" mkdir \"$(ProjectDir)..\\cli\\$(Configuration)\\modules\" - COMMAND copy /b /y \"$(TargetDir)*.dll\" \"$(ProjectDir)..\\cli\\$(Configuration)\\modules\" - COMMENT "Copy DLLs to target directory") - endif() -endif() - diff --git a/src/cpu-module-haxm/cpu_haxm.cpp b/src/cpu-module-haxm/cpu_haxm.cpp deleted file mode 100644 index adea3ba..0000000 --- a/src/cpu-module-haxm/cpu_haxm.cpp +++ /dev/null @@ -1,500 +0,0 @@ -#include -#include "cpu_haxm.h" - -#include "vixen/log.h" - -namespace vixen { -namespace cpu { - -HaxmCpu::HaxmCpu() { - m_haxm = nullptr; - m_vm = nullptr; - m_vcpu = nullptr; - - m_regsDirty = true; - m_fpuRegsDirty = true; - m_regsChanged = false; - m_fpuRegsChanged = false; -} - -HaxmCpu::~HaxmCpu() { - if (m_haxm != nullptr) { - // Deleting this object will automatically delete the VM and VCPU - delete m_haxm; - m_haxm = nullptr; - } -} - -CPUInitStatus HaxmCpu::InitializeImpl() { - if (m_haxm == nullptr) { - m_haxm = new Haxm(); - - auto status = m_haxm->Initialize(); - if (status != HXS_SUCCESS) { - return CPUS_INIT_PLATFORM_INIT_FAILED; - } - - auto vmStatus = m_haxm->CreateVM(&m_vm); - if (vmStatus != HXVMS_SUCCESS) { - delete m_haxm; - m_haxm = nullptr; - return CPUS_INIT_CREATE_VM_FAILED; - } - - auto vcpuStatus = m_vm->CreateVCPU(&m_vcpu); - if (vcpuStatus != HXVCPUS_SUCCESS) { - delete m_haxm; - m_haxm = nullptr; - return CPUS_INIT_CREATE_CPU_FAILED; - } - } - - return CPUS_INIT_OK; -} - -CPUStatus HaxmCpu::RunImpl() { - UpdateRegisters(); - auto status = m_vcpu->Run(); - return HandleExecResult(status); -} - -CPUStatus HaxmCpu::StepImpl() { - UpdateRegisters(); - auto status = m_vcpu->Step(); - return HandleExecResult(status); -} - -void HaxmCpu::UpdateRegisters() { - // Update CPU state if registers were modified - if (m_regsChanged) { - m_vcpu->SetRegisters(&m_regs); - m_regsChanged = false; - } - if (m_fpuRegsChanged) { - m_vcpu->SetFPURegisters(&m_fpuRegs); - m_fpuRegsChanged = false; - } -} - -CPUStatus HaxmCpu::HandleExecResult(HaxmVCPUStatus status) { - // Mark registers as dirty - m_regsDirty = true; - m_fpuRegsDirty = true; - - // Check VM exit status - if (status == HXVCPUS_FAILED) { - return CPUS_FAILED; - } - - auto tunnel = m_vcpu->Tunnel(); - - // Handle exit status using tunnel - switch (tunnel->_exit_status) { - case HAX_EXIT_HLT: m_exitInfo.reason = CPU_EXIT_HLT; break; // HLT instruction - case HAX_EXIT_IO: m_exitInfo.reason = CPU_EXIT_NORMAL; // I/O (in / out instructions) - return HandleIO(tunnel->io._df, tunnel->io._port, tunnel->io._direction, tunnel->io._size, tunnel->io._count, m_vcpu->IOTunnel()); - case HAX_EXIT_FAST_MMIO: m_exitInfo.reason = CPU_EXIT_NORMAL; // Fast MMIO - return HandleFastMMIO((struct hax_fastmmio *)m_vcpu->IOTunnel()); - case HAX_EXIT_INTERRUPT: m_exitInfo.reason = CPU_EXIT_NORMAL; break; // Let HAXM handle this - case HAX_EXIT_PAUSED: m_exitInfo.reason = CPU_EXIT_NORMAL; break; // Let HAXM handle this - case HAX_EXIT_MMIO: m_exitInfo.reason = CPU_EXIT_ERROR; break; // Regular MMIO (cannot be implemented) - case HAX_EXIT_REALMODE: m_exitInfo.reason = CPU_EXIT_ERROR; break; // Real mode is not supported - case HAX_EXIT_UNKNOWN: m_exitInfo.reason = CPU_EXIT_ERROR; break; // VM failed for an unknown reason - case HAX_EXIT_STATECHANGE: m_exitInfo.reason = CPU_EXIT_SHUTDOWN; break; // The VM is shutting down - case HAX_EXIT_DEBUG: // A breakpoint was hit - { - // Determine if it was a software or hardware breakpoint - if (tunnel->debug.dr6 & 0xf) { - m_exitInfo.reason = CPU_EXIT_HW_BREAKPOINT; - } - else { - m_exitInfo.reason = CPU_EXIT_SW_BREAKPOINT; - } - break; - } - } - - return CPUS_OK; -} - -InterruptResult HaxmCpu::InterruptImpl(uint8_t vector) { - return INTR_SUCCESS; -} - -CPUMemMapStatus HaxmCpu::MemMapSubregion(MemoryRegion *subregion) { - switch (subregion->m_type) { - case MEM_REGION_MMIO: - { - // All unmapped regions in a HAXM VM are MMIO, no need to allocate - return CPUS_MMAP_OK; - } - case MEM_REGION_NONE: - { - // This should not happen - assert(0); - return CPUS_MMAP_INVALID_TYPE; - } - case MEM_REGION_RAM: - case MEM_REGION_ROM: - { - // Region is either RAM or ROM, map it accordingly - HaxmVMMemoryType memType = subregion->m_type == MEM_REGION_RAM ? HXVM_MEM_RAM : HXVM_MEM_ROM; - auto status = m_vm->AllocateMemory(subregion->m_data, subregion->m_size, subregion->m_start, memType); - switch (status) { - case HXVMS_SUCCESS: return CPUS_MMAP_OK; - case HXVMS_MEM_MISALIGNED: return CPUS_MMAP_MEMORY_ADDR_MISALIGNED; - case HXVMS_MEMSIZE_MISALIGNED: return CPUS_MMAP_MEMORY_SIZE_MISALIGNED; - case HXVMS_ALLOC_MEM_FAILED: return CPUS_MMAP_MAPPING_FAILED; - case HXVMS_SET_MEM_FAILED: return CPUS_MMAP_MAPPING_FAILED; - default: return CPUS_MMAP_UNHANDLED_ERROR; - } - } - default: - // This should not happen - return CPUS_MMAP_INVALID_TYPE; - } -} - -#define REFRESH_REGISTERS do { \ - auto status = RefreshRegisters(false); \ - if (status) { \ - return status; \ - } \ -} while (0) - -CPUOperationStatus HaxmCpu::RegRead(enum CpuReg reg, uint32_t *value) { - REFRESH_REGISTERS; - - switch (reg) { - case REG_EIP: *value = m_regs._eip; break; - case REG_EFLAGS: *value = m_regs._eflags; break; - case REG_EAX: *value = m_regs._eax; break; - case REG_ECX: *value = m_regs._ecx; break; - case REG_EDX: *value = m_regs._edx; break; - case REG_EBX: *value = m_regs._ebx; break; - case REG_ESI: *value = m_regs._esi; break; - case REG_EDI: *value = m_regs._edi; break; - case REG_ESP: *value = m_regs._esp; break; - case REG_EBP: *value = m_regs._ebp; break; - case REG_CS: *value = m_regs._cs.selector; break; - case REG_SS: *value = m_regs._ss.selector; break; - case REG_DS: *value = m_regs._ds.selector; break; - case REG_ES: *value = m_regs._es.selector; break; - case REG_FS: *value = m_regs._fs.selector; break; - case REG_GS: *value = m_regs._gs.selector; break; - case REG_TR: *value = m_regs._tr.selector; break; - case REG_CR0: *value = m_regs._cr0; break; - case REG_CR2: *value = m_regs._cr2; break; - case REG_CR3: *value = m_regs._cr3; break; - case REG_CR4: *value = m_regs._cr4; break; - default: return CPUS_OP_INVALID_REGISTER; - } - - return CPUS_OP_OK; -} - -CPUOperationStatus HaxmCpu::RegWrite(enum CpuReg reg, uint32_t value) { - REFRESH_REGISTERS; - - switch (reg) { - case REG_EIP: m_regs._eip = value; break; - case REG_EFLAGS: m_regs._eflags = (value | 0x2) & ~0x8028; break; - case REG_EAX: m_regs._eax = value; break; - case REG_ECX: m_regs._ecx = value; break; - case REG_EDX: m_regs._edx = value; break; - case REG_EBX: m_regs._ebx = value; break; - case REG_ESI: m_regs._esi = value; break; - case REG_EDI: m_regs._edi = value; break; - case REG_ESP: m_regs._esp = value; break; - case REG_EBP: m_regs._ebp = value; break; - case REG_CS: LoadSegmentSelector((uint16_t)value, &m_regs._cs); break; - case REG_SS: LoadSegmentSelector((uint16_t)value, &m_regs._ss); break; - case REG_DS: LoadSegmentSelector((uint16_t)value, &m_regs._ds); break; - case REG_ES: LoadSegmentSelector((uint16_t)value, &m_regs._es); break; - case REG_FS: LoadSegmentSelector((uint16_t)value, &m_regs._fs); break; - case REG_GS: LoadSegmentSelector((uint16_t)value, &m_regs._gs); break; - case REG_TR: LoadSegmentSelector((uint16_t)value, &m_regs._tr); break; - case REG_CR0: m_regs._cr0 = value; break; - case REG_CR2: m_regs._cr2 = value; break; - case REG_CR3: m_regs._cr3 = value; break; - case REG_CR4: m_regs._cr4 = value; break; - default: return CPUS_OP_INVALID_REGISTER; - } - - m_regsChanged = true; - - return CPUS_OP_OK; -} - -CPUOperationStatus HaxmCpu::RegRead(CpuReg regs[], uint32_t values[], uint8_t numRegs) { - REFRESH_REGISTERS; - - for (uint8_t i = 0; i < numRegs; i++) { - switch (regs[i]) { - case REG_EIP: values[i] = m_regs._eip; break; - case REG_EFLAGS: values[i] = m_regs._eflags; break; - case REG_EAX: values[i] = m_regs._eax; break; - case REG_ECX: values[i] = m_regs._ecx; break; - case REG_EDX: values[i] = m_regs._edx; break; - case REG_EBX: values[i] = m_regs._ebx; break; - case REG_ESI: values[i] = m_regs._esi; break; - case REG_EDI: values[i] = m_regs._edi; break; - case REG_ESP: values[i] = m_regs._esp; break; - case REG_EBP: values[i] = m_regs._ebp; break; - case REG_CS: values[i] = m_regs._cs.selector; break; - case REG_SS: values[i] = m_regs._ss.selector; break; - case REG_DS: values[i] = m_regs._ds.selector; break; - case REG_ES: values[i] = m_regs._es.selector; break; - case REG_FS: values[i] = m_regs._fs.selector; break; - case REG_GS: values[i] = m_regs._gs.selector; break; - case REG_TR: values[i] = m_regs._tr.selector; break; - case REG_CR0: values[i] = m_regs._cr0; break; - case REG_CR2: values[i] = m_regs._cr2; break; - case REG_CR3: values[i] = m_regs._cr3; break; - case REG_CR4: values[i] = m_regs._cr4; break; - default: return CPUS_OP_INVALID_REGISTER; - } - } - - return CPUS_OP_OK; -} - -CPUOperationStatus HaxmCpu::RegWrite(CpuReg regs[], uint32_t values[], uint8_t numRegs) { - REFRESH_REGISTERS; - - for (uint8_t i = 0; i < numRegs; i++) { - switch (regs[i]) { - case REG_EIP: m_regs._eip = values[i]; break; - case REG_EFLAGS: m_regs._eflags = (values[i] | 0x2) & ~0x8028; break; - case REG_EAX: m_regs._eax = values[i]; break; - case REG_ECX: m_regs._ecx = values[i]; break; - case REG_EDX: m_regs._edx = values[i]; break; - case REG_EBX: m_regs._ebx = values[i]; break; - case REG_ESI: m_regs._esi = values[i]; break; - case REG_EDI: m_regs._edi = values[i]; break; - case REG_ESP: m_regs._esp = values[i]; break; - case REG_EBP: m_regs._ebp = values[i]; break; - case REG_CS: LoadSegmentSelector(values[i], &m_regs._cs); break; - case REG_SS: LoadSegmentSelector(values[i], &m_regs._ss); break; - case REG_DS: LoadSegmentSelector(values[i], &m_regs._ds); break; - case REG_ES: LoadSegmentSelector(values[i], &m_regs._es); break; - case REG_FS: LoadSegmentSelector(values[i], &m_regs._fs); break; - case REG_GS: LoadSegmentSelector(values[i], &m_regs._gs); break; - case REG_TR: LoadSegmentSelector(values[i], &m_regs._tr); break; - case REG_CR0: m_regs._cr0 = values[i]; break; - case REG_CR2: m_regs._cr2 = values[i]; break; - case REG_CR3: m_regs._cr3 = values[i]; break; - case REG_CR4: m_regs._cr4 = values[i]; break; - default: return CPUS_OP_INVALID_REGISTER; - } - } - - m_regsChanged = true; - - return CPUS_OP_OK; -} - -CPUOperationStatus HaxmCpu::GetGDT(uint32_t *addr, uint32_t *size) { - REFRESH_REGISTERS; - - *addr = m_regs._gdt.base; - *size = m_regs._gdt.limit; - - return CPUS_OP_OK; -} - -CPUOperationStatus HaxmCpu::SetGDT(uint32_t addr, uint32_t size) { - REFRESH_REGISTERS; - - m_regs._gdt.base = addr; - m_regs._gdt.limit = size; - - m_regsChanged = true; - - return CPUS_OP_OK; -} - -CPUOperationStatus HaxmCpu::GetIDT(uint32_t *addr, uint32_t *size) { - REFRESH_REGISTERS; - - *addr = m_regs._idt.base; - *size = m_regs._idt.limit; - - return CPUS_OP_OK; -} - -CPUOperationStatus HaxmCpu::SetIDT(uint32_t addr, uint32_t size) { - REFRESH_REGISTERS; - - m_regs._idt.base = addr; - m_regs._idt.limit = size; - - m_regsChanged = true; - - return CPUS_OP_OK; -} - -CPUOperationStatus HaxmCpu::EnableSoftwareBreakpoints(bool enable) { - auto status = m_vcpu->EnableSoftwareBreakpoints(enable); - if (status != HXVCPUS_SUCCESS) { - return CPUS_OP_FAILED; - } - - return CPUS_OP_OK; -} - -CPUOperationStatus HaxmCpu::SetHardwareBreakpoints(HardwareBreakpoints breakpoints) { - HaxmHardwareBreakpoint bps[4]; - for (int i = 0; i < 4; i++) { - bps[i].address = breakpoints.bp[0].address; - bps[i].localEnable = breakpoints.bp[0].localEnable; - bps[i].globalEnable = breakpoints.bp[0].globalEnable; - bps[i].trigger = (HaxmHardwareBreakpointTrigger)breakpoints.bp[0].trigger; - bps[i].length = (HaxmHardwareBreakpointLength)breakpoints.bp[0].length; - } - - auto status = m_vcpu->SetHardwareBreakpoints(bps); - if (status != HXVCPUS_SUCCESS) { - return CPUS_OP_FAILED; - } - - return CPUS_OP_OK; -} - -CPUOperationStatus HaxmCpu::ClearHardwareBreakpoints() { - auto status = m_vcpu->ClearHardwareBreakpoints(); - if (status != HXVCPUS_SUCCESS) { - return CPUS_OP_FAILED; - } - - return CPUS_OP_OK; -} - -CPUOperationStatus HaxmCpu::GetBreakpointAddress(uint32_t *address) { - auto debugTunnel = &m_vcpu->Tunnel()->debug; - char hardwareBP = debugTunnel->dr6 & 0xF; - - // No breakpoints were hit - if (hardwareBP == 0 && debugTunnel->rip == 0) { - return CPUS_OP_BREAKPOINT_NEVER_HIT; - } - - // Get the appropriate breakpoint address - auto debug = m_vcpu->Debug(); - /**/ if (hardwareBP & (1 << 0)) *address = debug->dr[0]; - else if (hardwareBP & (1 << 1)) *address = debug->dr[1]; - else if (hardwareBP & (1 << 2)) *address = debug->dr[2]; - else if (hardwareBP & (1 << 3)) *address = debug->dr[3]; - else /************************/ *address = (uint32_t)debugTunnel->rip; - - return CPUS_OP_OK; -} - -CPUStatus HaxmCpu::HandleIO(uint8_t df, uint16_t port, uint8_t direction, uint16_t size, uint16_t count, uint8_t *buffer) { - uint8_t *ptr; - if (df) { - ptr = buffer + size * count - size; - } - else { - ptr = buffer; - } - - for (uint16_t i = 0; i < count; i++) { - if (direction == HAX_IO_OUT) { - uint32_t value; - switch (size) { - case 1: value = *ptr; break; - case 2: value = *reinterpret_cast(ptr); break; - case 4: value = *reinterpret_cast(ptr); break; - default: assert(0); // should not happen - } - m_ioMapper->IOWrite(port, value, size); - } - else { - m_ioMapper->IORead(port, reinterpret_cast(ptr), size); - } - - if (df) { - ptr -= size; - } - else { - ptr += size; - } - } - - return CPUS_OK; -} - -CPUStatus HaxmCpu::HandleFastMMIO(struct hax_fastmmio *info) { - if (info->direction < 2) { - if (info->direction == HAX_IO_IN) { - m_ioMapper->MMIOWrite(info->gpa, (uint32_t)info->value, info->size); - } - else { - m_ioMapper->MMIORead(info->gpa, (uint32_t*)&info->value, info->size); - } - } - else { - // HAX API v4 supports transferring data between two MMIO addresses, - // info->gpa and info->gpa2 (instructions such as MOVS require this): - // info->direction == 2: gpa ==> gpa2 - - uint32_t value; - m_ioMapper->MMIORead(info->gpa, &value, info->size); - m_ioMapper->MMIOWrite(info->gpa2, value, info->size); - } - return CPUS_OK; -} - -CPUOperationStatus HaxmCpu::RefreshRegisters(bool refreshFPU) { - if (m_regsDirty) { - if (m_vcpu->GetRegisters(&m_regs) != HXVCPUS_SUCCESS) { - return CPUS_OP_FAILED; - } - - if (refreshFPU) { - m_vcpu->GetFPURegisters(&m_fpuRegs); - } - - m_regsDirty = false; - } - return CPUS_OP_OK; -} - -int HaxmCpu::LoadSegmentSelector(uint16_t selector, segment_desc_t *segment) { - // Set basic register data - segment->selector = selector; - - // Get GDT entry from memory - GDTEntry gdtEntry; - VMemRead(m_regs._gdt.base + selector, sizeof(GDTEntry), &gdtEntry); - - // Fill in the rest of the CS info with data from the GDT entry - segment->ar = gdtEntry.data.access | (gdtEntry.data.flags << 12); - segment->base = gdtEntry.GetBase(); - segment->limit = gdtEntry.GetLimit(); - - m_regsChanged = true; - - return 0; -} - -CPUOperationStatus HaxmCpu::InjectInterrupt(uint8_t vector) { - auto status = m_vcpu->Interrupt(vector); - if (status != HXVCPUS_SUCCESS) { - return CPUS_OP_FAILED; - } - m_vcpu->Tunnel()->request_interrupt_window = 0; - return CPUS_OP_OK; -} - -bool HaxmCpu::CanInjectInterrupt() { - return m_vcpu->Tunnel()->ready_for_interrupt_injection != 0; -} - -void HaxmCpu::RequestInterruptWindow() { - m_vcpu->Tunnel()->request_interrupt_window = 1; -} - -} -} diff --git a/src/cpu-module-haxm/cpu_haxm.h b/src/cpu-module-haxm/cpu_haxm.h deleted file mode 100644 index 57cda71..0000000 --- a/src/cpu-module-haxm/cpu_haxm.h +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once - -#include "haxm/haxm.h" -#include "vixen/cpu.h" -#include "vixen/bitmap.h" - -#include -#include - -namespace vixen { -namespace cpu { - -/*! - * Intel HAXM CPU implementation. - * - * This is the implementation of the CPU interface using - * [Intel HAXM](https://software.intel.com/en-us/articles/intel-hardware-accelerated-execution-manager-intel-haxm). - */ -class HaxmCpu : public Cpu { -public: - HaxmCpu(); - ~HaxmCpu(); - - CPUInitStatus InitializeImpl(); - - CPUStatus RunImpl(); - CPUStatus StepImpl(); - InterruptResult InterruptImpl(uint8_t vector); - - CPUMemMapStatus MemMapSubregion(MemoryRegion *subregion); - - CPUOperationStatus RegRead(enum CpuReg reg, uint32_t *value); - CPUOperationStatus RegWrite(enum CpuReg reg, uint32_t value); - - CPUOperationStatus RegRead(enum CpuReg regs[], uint32_t values[], uint8_t numRegs) override; - CPUOperationStatus RegWrite(enum CpuReg regs[], uint32_t values[], uint8_t numRegs) override; - - CPUOperationStatus GetGDT(uint32_t *addr, uint32_t *size); - CPUOperationStatus SetGDT(uint32_t addr, uint32_t size); - - CPUOperationStatus GetIDT(uint32_t *addr, uint32_t *size); - CPUOperationStatus SetIDT(uint32_t addr, uint32_t size); - - CPUOperationStatus EnableSoftwareBreakpoints(bool enable) override; - CPUOperationStatus SetHardwareBreakpoints(HardwareBreakpoints breakpoints) override; - CPUOperationStatus ClearHardwareBreakpoints() override; - CPUOperationStatus GetBreakpointAddress(uint32_t *address) override; - -protected: - CPUOperationStatus InjectInterrupt(uint8_t vector); - bool CanInjectInterrupt(); - void RequestInterruptWindow(); - -private: - Haxm *m_haxm; - HaxmVM *m_vm; - HaxmVCPU *m_vcpu; - - vcpu_state_t m_regs; - fx_layout m_fpuRegs; - bool m_regsDirty; // set to true on VM exit to indicate that general registers need to be refreshed - bool m_fpuRegsDirty; // set to true on VM exit to indicate that floating point registers need to be refreshed - bool m_regsChanged; // set to true when general registers are modified by the host - bool m_fpuRegsChanged; // set to true when floating point registers are modified by the host - - void UpdateRegisters(); - CPUStatus HandleExecResult(HaxmVCPUStatus status); - - CPUStatus HandleIO(uint8_t df, uint16_t port, uint8_t direction, uint16_t size, uint16_t count, uint8_t *buffer); - CPUStatus HandleFastMMIO(struct hax_fastmmio *info); - - CPUOperationStatus RefreshRegisters(bool refreshFPU); - - int LoadSegmentSelector(uint16_t selector, segment_desc_t *segment); -}; - -} -} diff --git a/src/cpu-module-haxm/cpu_haxm_module.cpp b/src/cpu-module-haxm/cpu_haxm_module.cpp deleted file mode 100644 index 32f098e..0000000 --- a/src/cpu-module-haxm/cpu_haxm_module.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include - -#include "vixen/cpu_module_decl.h" -#include "cpu_haxm_module.h" -#include "cpu_haxm.h" - -namespace vixen { -namespace modules { -namespace cpu { - -CPU_MODULE_BEGIN -CPU_MODULE_INFO(HaxmCPUModule, "Intel HAXM CPU Module", "0.0.1") -CPU_MODULE_CAPS.guestDebugging(); -CPU_MODULE_END - -Cpu *HaxmCPUModule::GetCPU() { - return &m_cpu; -} - -void HaxmCPUModule::FreeCPU(Cpu *cpu) { -} - -void HaxmCPUModule::Cleanup() { -} - -} -} -} diff --git a/src/cpu-module-haxm/cpu_haxm_module.h b/src/cpu-module-haxm/cpu_haxm_module.h deleted file mode 100644 index 824dcda..0000000 --- a/src/cpu-module-haxm/cpu_haxm_module.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "vixen/cpu.h" -#include "cpu_haxm.h" - -namespace vixen { -namespace modules { -namespace cpu { - -using namespace vixen::cpu; - -class HaxmCPUModule : public ICPUModule { -public: - Cpu *GetCPU(); - void FreeCPU(Cpu *cpu); - void Cleanup(); -private: - HaxmCpu m_cpu; -}; - -} -} -} diff --git a/src/cpu-module-haxm/haxm/darwin/hax_interface_mac.h b/src/cpu-module-haxm/haxm/darwin/hax_interface_mac.h deleted file mode 100644 index 2d86870..0000000 --- a/src/cpu-module-haxm/haxm/darwin/hax_interface_mac.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2011 Intel Corporation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HAX_DARWIN_HAX_INTERFACE_MAC_H_ -#define HAX_DARWIN_HAX_INTERFACE_MAC_H_ - -#include - -/* The mac specific interface to qemu because of mac's - * special handling like hax tunnel allocation etc */ -/* HAX model level ioctl */ -#define HAX_IOCTL_VERSION _IOWR(0, 0x20, struct hax_module_version) -#define HAX_IOCTL_CREATE_VM _IOWR(0, 0x21, uint32_t) -#define HAX_IOCTL_DESTROY_VM _IOW(0, 0x22, uint32_t) -#define HAX_IOCTL_CAPABILITY _IOR(0, 0x23, struct hax_capabilityinfo) -#define HAX_IOCTL_SET_MEMLIMIT _IOWR(0, 0x24, struct hax_set_memlimit) - -// Only for backward compatibility with old Qemu. -#define HAX_VM_IOCTL_VCPU_CREATE_ORIG _IOR(0, 0x80, int) - -#define HAX_VM_IOCTL_VCPU_CREATE _IOWR(0, 0x80, uint32_t) -#define HAX_VM_IOCTL_ALLOC_RAM _IOWR(0, 0x81, struct hax_alloc_ram_info) -#define HAX_VM_IOCTL_SET_RAM _IOWR(0, 0x82, struct hax_set_ram_info) -#define HAX_VM_IOCTL_VCPU_DESTROY _IOR(0, 0x83, uint32_t) -#define HAX_VM_IOCTL_ADD_RAMBLOCK _IOW(0, 0x85, struct hax_ramblock_info) -#define HAX_VM_IOCTL_SET_RAM2 _IOWR(0, 0x86, struct hax_set_ram_info2) -#define HAX_VM_IOCTL_PROTECT_RAM _IOWR(0, 0x87, struct hax_protect_ram_info) - -#define HAX_VCPU_IOCTL_RUN _IO(0, 0xc0) -#define HAX_VCPU_IOCTL_SET_MSRS _IOWR(0, 0xc1, struct hax_msr_data) -#define HAX_VCPU_IOCTL_GET_MSRS _IOWR(0, 0xc2, struct hax_msr_data) - -#define HAX_VCPU_IOCTL_SET_FPU _IOW(0, 0xc3, struct fx_layout) -#define HAX_VCPU_IOCTL_GET_FPU _IOR(0, 0xc4, struct fx_layout) - -#define HAX_VCPU_IOCTL_SETUP_TUNNEL _IOWR(0, 0xc5, struct hax_tunnel_info) -#define HAX_VCPU_IOCTL_INTERRUPT _IOWR(0, 0xc6, uint32_t) -#define HAX_VCPU_SET_REGS _IOWR(0, 0xc7, struct vcpu_state_t) -#define HAX_VCPU_GET_REGS _IOWR(0, 0xc8, struct vcpu_state_t) - -/* API 2.0 */ -#define HAX_VM_IOCTL_NOTIFY_QEMU_VERSION _IOW(0, 0x84, struct hax_qemu_version) - -#define HAX_IOCTL_VCPU_DEBUG _IOW(0, 0xc9, struct hax_debug_t) - - -#endif // HAX_DARWIN_HAX_INTERFACE_MAC_H_ diff --git a/src/cpu-module-haxm/haxm/darwin/hax_types_mac.h b/src/cpu-module-haxm/haxm/darwin/hax_types_mac.h deleted file mode 100644 index f56a473..0000000 --- a/src/cpu-module-haxm/haxm/darwin/hax_types_mac.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2011 Intel Corporation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HAX_DARWIN_HAX_TYPES_MAC_H_ -#define HAX_DARWIN_HAX_TYPES_MAC_H_ - -// Unsigned Types -typedef unsigned long ulong; - -typedef ulong mword; - -#endif // HAX_DARWIN_HAX_TYPES_MAC_H_ diff --git a/src/cpu-module-haxm/haxm/hax_interface.h b/src/cpu-module-haxm/haxm/hax_interface.h deleted file mode 100644 index 41efd2b..0000000 --- a/src/cpu-module-haxm/haxm/hax_interface.h +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (c) 2011 Intel Corporation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HAX_INTERFACE_H_ -#define HAX_INTERFACE_H_ - -/* - * The interface to QEMU, notice: - * 1) not include any file other than top level include - * 2) will be shared by QEMU and kernel - */ - -#include "hax_types.h" - -#ifdef HAX_PLATFORM_DARWIN -#include "darwin/hax_interface_mac.h" -#endif -#ifdef HAX_PLATFORM_LINUX -#include "linux/hax_interface_linux.h" -#endif -#ifdef HAX_PLATFORM_WINDOWS -#include "windows/hax_interface_windows.h" -#endif - -#include "vcpu_state.h" - -struct vmx_msr { - uint64_t entry; - uint64_t value; -} PACKED; - -/* fx_layout has 3 formats table 3-56, 512bytes */ -struct fx_layout { - uint16_t fcw; - uint16_t fsw; - uint8_t ftw; - uint8_t res1; - uint16_t fop; - union { - struct { - uint32_t fip; - uint16_t fcs; - uint16_t res2; - }; - uint64_t fpu_ip; - }; - union { - struct { - uint32_t fdp; - uint16_t fds; - uint16_t res3; - }; - uint64_t fpu_dp; - }; - uint32_t mxcsr; - uint32_t mxcsr_mask; - uint8_t st_mm[8][16]; - uint8_t mmx_1[8][16]; - uint8_t mmx_2[8][16]; - uint8_t pad[96]; -} ALIGNED(16); - -/* - * TODO: Fixed array is stupid, but it makes Mac support a bit easier, since we - * can avoid the memory map or copyin staff. We need to fix it in future. - */ - -#define HAX_MAX_MSR_ARRAY 0x20 -struct hax_msr_data { - uint16_t nr_msr; - uint16_t done; - uint16_t pad[2]; - struct vmx_msr entries[HAX_MAX_MSR_ARRAY]; -} PACKED; - -#define HAX_IO_OUT 0 -#define HAX_IO_IN 1 - -/* The area to communicate with device model */ -struct hax_tunnel { - uint32_t _exit_reason; - uint32_t pad0; - uint32_t _exit_status; - uint32_t user_event_pending; - int ready_for_interrupt_injection; - int request_interrupt_window; - - union { - struct { - uint8_t _direction; - uint8_t _df; - uint16_t _size; - uint16_t _port; - uint16_t _count; - /* Followed owned by HAXM, QEMU should not touch them */ - /* bit 1 is 1 means string io */ - uint8_t _flags; - uint8_t _pad0; - uint16_t _pad1; - uint32_t _pad2; - hax_vaddr_t _vaddr; - } io; - struct { - hax_paddr_t gla; - } mmio; - struct { - hax_paddr_t gpa; -#define HAX_PAGEFAULT_ACC_R (1 << 0) -#define HAX_PAGEFAULT_ACC_W (1 << 1) -#define HAX_PAGEFAULT_ACC_X (1 << 2) -#define HAX_PAGEFAULT_PERM_R (1 << 4) -#define HAX_PAGEFAULT_PERM_W (1 << 5) -#define HAX_PAGEFAULT_PERM_X (1 << 6) - uint32_t flags; - uint32_t reserved1; - uint64_t reserved2; - } pagefault; - struct { - hax_paddr_t dummy; - } state; - struct { - uint64_t rip; - uint64_t dr6; - uint64_t dr7; - } debug; - }; - uint64_t apic_base; -} PACKED; - -struct hax_fastmmio { - hax_paddr_t gpa; - union { - uint64_t value; - hax_paddr_t gpa2; /* since API v4 */ - }; - uint8_t size; - uint8_t direction; - uint16_t reg_index; /* obsolete */ - uint32_t pad0; - uint64_t _cr0; - uint64_t _cr2; - uint64_t _cr3; - uint64_t _cr4; -} PACKED; - -struct hax_module_version { - uint32_t compat_version; - uint32_t cur_version; -} PACKED; - -#define HAX_CAP_STATUS_WORKING (1 << 0) -#define HAX_CAP_MEMQUOTA (1 << 1) -#define HAX_CAP_WORKSTATUS_MASK 0x01 - -#define HAX_CAP_FAILREASON_VT (1 << 0) -#define HAX_CAP_FAILREASON_NX (1 << 1) - -#define HAX_CAP_EPT (1 << 0) -#define HAX_CAP_FASTMMIO (1 << 1) -#define HAX_CAP_UG (1 << 2) -#define HAX_CAP_64BIT_RAMBLOCK (1 << 3) -#define HAX_CAP_64BIT_SETRAM (1 << 4) -#define HAX_CAP_TUNNEL_PAGE (1 << 5) -#define HAX_CAP_RAM_PROTECTION (1 << 6) -#define HAX_CAP_DEBUG (1 << 7) - -struct hax_capabilityinfo { - /* - * bit 0: 1 - working, 0 - not working, possibly because NT/NX disabled - * bit 1: 1 - memory limitation working, 0 - no memory limitation - */ - uint16_t wstatus; - /* - * valid when not working - * bit0: VT not enabeld - * bit1: NX not enabled - */ - /* - * valid when working - * bit0: EPT enabled - * bit1: fastMMIO - */ - uint16_t winfo; - uint32_t win_refcount; - uint64_t mem_quota; -} PACKED; - -struct hax_tunnel_info { - uint64_t va; - uint64_t io_va; - uint16_t size; - uint16_t pad[3]; -} PACKED; - -struct hax_set_memlimit { - uint8_t enable_memlimit; - uint8_t pad[7]; - uint64_t memory_limit; -} PACKED; - -struct hax_alloc_ram_info { - uint32_t size; - uint32_t pad; - uint64_t va; -} PACKED; - -struct hax_ramblock_info { - uint64_t start_va; - uint64_t size; - uint64_t reserved; -} PACKED; - -#define HAX_RAM_INFO_ROM 0x01 // read-only -#define HAX_RAM_INFO_INVALID 0x80 // unmapped, usually used for MMIO - -struct hax_set_ram_info { - uint64_t pa_start; - uint32_t size; - uint8_t flags; - uint8_t pad[3]; - uint64_t va; -} PACKED; - -struct hax_set_ram_info2 { - uint64_t pa_start; - uint64_t size; - uint64_t va; - uint32_t flags; - uint32_t reserved1; - uint64_t reserved2; -} PACKED; - -// No access (R/W/X) is allowed -#define HAX_RAM_PERM_NONE 0x0 -// All accesses (R/W/X) are allowed -#define HAX_RAM_PERM_RWX 0x7 -#define HAX_RAM_PERM_MASK 0x7 -struct hax_protect_ram_info { - uint64_t pa_start; - uint64_t size; - uint32_t flags; - uint32_t reserved; -} PACKED; - -/* This interface is support only after API version 2 */ -struct hax_qemu_version { - /* Current API version in QEMU*/ - uint32_t cur_version; - /* The least API version supported by QEMU */ - uint32_t least_version; -} PACKED; - -#define HAX_DEBUG_ENABLE (1 << 0) -#define HAX_DEBUG_STEP (1 << 1) -#define HAX_DEBUG_USE_SW_BP (1 << 2) -#define HAX_DEBUG_USE_HW_BP (1 << 3) - -struct hax_debug_t { - uint32_t control; - uint32_t reserved; - uint64_t dr[8]; -} PACKED; - -#endif // HAX_INTERFACE_H_ diff --git a/src/cpu-module-haxm/haxm/hax_types.h b/src/cpu-module-haxm/haxm/hax_types.h deleted file mode 100644 index a4e0437..0000000 --- a/src/cpu-module-haxm/haxm/hax_types.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2011 Intel Corporation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HAX_TYPES_H_ -#define HAX_TYPES_H_ - -/* Detect architecture */ -// x86 (32-bit) -#if defined(__i386__) || defined(_M_IX86) -#define HAX_ARCH_X86_32 -#define ASMCALL __cdecl -// x86 (64-bit) -#elif defined(__x86_64__) || defined(_M_X64) -#define HAX_ARCH_X86_64 -#define ASMCALL -#else -#error "Unsupported architecture" -#endif - -/* Detect compiler */ -// Clang -#if defined(__clang__) -#define HAX_COMPILER_CLANG -#define PACKED __attribute__ ((packed)) -#define ALIGNED(x) __attribute__ ((aligned(x))) -// GCC -#elif defined(__GNUC__) -#define HAX_COMPILER_GCC -#define PACKED __attribute__ ((packed)) -#define ALIGNED(x) __attribute__ ((aligned(x))) -#define __cdecl __attribute__ ((__cdecl__,regparm(0))) -#define __stdcall __attribute__ ((__stdcall__)) -// MSVC -#elif defined(_MSC_VER) -#define HAX_COMPILER_MSVC -// FIXME: MSVC doesn't have a simple equivalent for PACKED. -// Instead, The corresponding #pragma directives are added manually. -#define PACKED -#define ALIGNED(x) __declspec(align(x)) -#else -#error "Unsupported compiler" -#endif - -/* Detect platform */ -#ifndef HAX_TESTS // Prevent kernel-only exports from reaching userland code -// MacOS -#if defined(__MACH__) -#define HAX_PLATFORM_DARWIN -#include "darwin/hax_types_mac.h" -// Linux -#elif defined(__linux__) -#define HAX_PLATFORM_LINUX -#include "linux/hax_types_linux.h" -// Windows -#elif defined(_WIN32) -#define HAX_PLATFORM_WINDOWS -#include "windows/hax_types_windows.h" -#else -#error "Unsupported platform" -#endif -#else // !HAX_TESTS -#include -#endif // HAX_TESTS - -#define HAX_PAGE_SIZE 4096 -#define HAX_PAGE_SHIFT 12 -#define HAX_PAGE_MASK 0xfff - -/* Common typedef for all platforms */ -typedef uint64_t hax_pa_t; -typedef uint64_t hax_pfn_t; -typedef uint64_t hax_paddr_t; -typedef uint64_t hax_vaddr_t; - -enum exit_status { - HAX_EXIT_IO = 1, - HAX_EXIT_MMIO, - HAX_EXIT_REALMODE, - HAX_EXIT_INTERRUPT, - HAX_EXIT_UNKNOWN, - HAX_EXIT_HLT, - HAX_EXIT_STATECHANGE, - HAX_EXIT_PAUSED, - HAX_EXIT_FAST_MMIO, - HAX_EXIT_PAGEFAULT, - HAX_EXIT_DEBUG -}; - -enum { - VMX_EXIT_INT_EXCEPTION_NMI = 0, // An SW interrupt, exception or NMI has occurred - VMX_EXIT_EXT_INTERRUPT = 1, // An external interrupt has occurred - VMX_EXIT_TRIPLE_FAULT = 2, // Triple fault occurred - VMX_EXIT_INIT_EVENT = 3, // INIT signal arrived - VMX_EXIT_SIPI_EVENT = 4, // SIPI signal arrived - VMX_EXIT_SMI_IO_EVENT = 5, - VMX_EXIT_SMI_OTHER_EVENT = 6, - VMX_EXIT_PENDING_INTERRUPT = 7, - VMX_EXIT_PENDING_NMI = 8, - VMX_EXIT_TASK_SWITCH = 9, // Guest attempted a task switch - VMX_EXIT_CPUID = 10, // Guest executed CPUID instruction - VMX_EXIT_GETSEC = 11, // Guest executed GETSEC instruction - VMX_EXIT_HLT = 12, // Guest executed HLT instruction - VMX_EXIT_INVD = 13, // Guest executed INVD instruction - VMX_EXIT_INVLPG = 14, // Guest executed INVLPG instruction - VMX_EXIT_RDPMC = 15, // Guest executed RDPMC instruction - VMX_EXIT_RDTSC = 16, // Guest executed RDTSC instruction - VMX_EXIT_RSM = 17, // Guest executed RSM instruction in SMM - VMX_EXIT_VMCALL = 18, - VMX_EXIT_VMCLEAR = 19, - VMX_EXIT_VMLAUNCH = 20, - VMX_EXIT_VMPTRLD = 21, - VMX_EXIT_VMPTRST = 22, - VMX_EXIT_VMREAD = 23, - VMX_EXIT_VMRESUME = 24, - VMX_EXIT_VMWRITE = 25, - VMX_EXIT_VMXOFF = 26, - VMX_EXIT_VMXON = 27, - VMX_EXIT_CR_ACCESS = 28, // Guest accessed a control register - VMX_EXIT_DR_ACCESS = 29, // Guest attempted access to debug register - VMX_EXIT_IO = 30, // Guest attempted I/O - VMX_EXIT_MSR_READ = 31, // Guest attempted to read an MSR - VMX_EXIT_MSR_WRITE = 32, // Guest attempted to write an MSR - VMX_EXIT_FAILED_VMENTER_GS = 33, // VMENTER failed due to guest state - VMX_EXIT_FAILED_VMENTER_MSR = 34, // VMENTER failed due to MSR loading - VMX_EXIT_MWAIT = 36, - VMX_EXIT_MTF_EXIT = 37, - VMX_EXIT_MONITOR = 39, - VMX_EXIT_PAUSE = 40, - VMX_EXIT_MACHINE_CHECK = 41, - VMX_EXIT_TPR_BELOW_THRESHOLD = 43, - VMX_EXIT_APIC_ACCESS = 44, - VMX_EXIT_GDT_IDT_ACCESS = 46, - VMX_EXIT_LDT_TR_ACCESS = 47, - VMX_EXIT_EPT_VIOLATION = 48, - VMX_EXIT_EPT_MISCONFIG = 49, - VMX_EXIT_INVEPT = 50, - VMX_EXIT_RDTSCP = 51, - VMX_EXIT_VMX_TIMER_EXIT = 52, - VMX_EXIT_INVVPID = 53, - VMX_EXIT_WBINVD = 54, - VMX_EXIT_XSETBV = 55, - VMX_EXIT_APIC_WRITE = 56, - VMX_EXIT_RDRAND = 57, - VMX_EXIT_INVPCID = 58, - VMX_EXIT_VMFUNC = 59, - VMX_EXIT_ENCLS = 60, - VMX_EXIT_RDSEED = 61, - VMX_EXIT_XSAVES = 63, - VMX_EXIT_XRSTORS = 64 -}; - -#endif // HAX_TYPES_H_ diff --git a/src/cpu-module-haxm/haxm/haxm.cpp b/src/cpu-module-haxm/haxm/haxm.cpp deleted file mode 100644 index 9d3e70c..0000000 --- a/src/cpu-module-haxm/haxm/haxm.cpp +++ /dev/null @@ -1,687 +0,0 @@ -#include "haxm.h" - -Haxm::Haxm() - : m_hHAXM(INVALID_HANDLE_VALUE) - , m_lastError(ERROR_SUCCESS) - , m_ver({ 0 }) - , m_caps({ 0 }) -{ -} - -Haxm::~Haxm() { - if (m_hHAXM != INVALID_HANDLE_VALUE) { - // Close VMs - for (auto it = m_vms.begin(); it != m_vms.end(); it++) { - (*it)->Close(); - delete (*it); - } - m_vms.clear(); - - CloseHandle(m_hHAXM); - m_hHAXM = INVALID_HANDLE_VALUE; - } -} - -HaxmStatus Haxm::Initialize() { - if (m_hHAXM != INVALID_HANDLE_VALUE) { - return HXS_SUCCESS; - } - - // Open the device - m_hHAXM = CreateFileW(L"\\\\.\\HAX", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (m_hHAXM == INVALID_HANDLE_VALUE) { - m_lastError = GetLastError(); - return HXS_NOT_FOUND; - } - - DWORD returnSize; - BOOLEAN bResult; - - // Retrieve version - bResult = DeviceIoControl(m_hHAXM, - HAX_IOCTL_VERSION, - NULL, 0, - &m_ver, sizeof(m_ver), - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - CloseHandle(m_hHAXM); - m_hHAXM = INVALID_HANDLE_VALUE; - m_lastError = GetLastError(); - return HXS_INIT_FAILED; - } - - // Retrieve capabilities - bResult = DeviceIoControl(m_hHAXM, - HAX_IOCTL_CAPABILITY, - NULL, 0, - &m_caps, sizeof(m_caps), - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - CloseHandle(m_hHAXM); - m_hHAXM = INVALID_HANDLE_VALUE; - m_lastError = GetLastError(); - return HXS_INIT_FAILED; - } - - return HXS_SUCCESS; -} - -HaxmStatus Haxm::SetGlobalMemoryLimit(bool enabled, uint64_t limitMB) { - DWORD returnSize; - BOOLEAN bResult; - - struct hax_set_memlimit memlimit; - memlimit.enable_memlimit = enabled; - memlimit.memory_limit = enabled ? limitMB : 0; - bResult = DeviceIoControl(m_hHAXM, - HAX_IOCTL_SET_MEMLIMIT, - &memlimit, sizeof(memlimit), - NULL, 0, - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - m_lastError = GetLastError(); - return HXS_SET_MEM_LIMIT_FAILED; - } - return HXS_SUCCESS; -} - -HaxmVMStatus Haxm::CreateVM(HaxmVM **vm) { - *vm = new HaxmVM(*this); - HaxmVMStatus status = (*vm)->Initialize(); - if (status != HXS_SUCCESS) { - m_lastError = GetLastError(); - delete *vm; - *vm = nullptr; - } - else { - m_vms.push_back(*vm); - } - return status; -} - -// ---------------------------------------------------------------------------- - -HaxmVM::HaxmVM(Haxm& haxm) - : m_haxm(haxm) - , m_hVM(INVALID_HANDLE_VALUE) - , m_vmID(-1) - , m_fastMMIO(false) - , m_nextVCPUID(0) - , m_lastError(ERROR_SUCCESS) -{ -} - -HaxmVM::~HaxmVM() { - Close(); -} - -HaxmVMStatus HaxmVM::Initialize() { - DWORD returnSize; - BOOLEAN bResult; - - // Ask HAXM to create a VM - bResult = DeviceIoControl(m_haxm.Handle(), - HAX_IOCTL_CREATE_VM, - NULL, 0, - &m_vmID, sizeof(m_vmID), - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - return HXVMS_CREATE_FAILED; - } - - // VM created successfully; open the object - wchar_t vmName[13]; - swprintf_s(vmName, L"\\\\.\\hax_vm%02d", m_vmID); - m_hVM = CreateFileW(vmName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (m_hVM == INVALID_HANDLE_VALUE) { - m_vmID = -1; - Close(); - return HXVMS_CREATE_FAILED; - } - - // Report QEMU API version 4 to enable fast MMIO - if (m_haxm.GetCapabilities()->winfo & HAX_CAP_FASTMMIO) { - struct hax_qemu_version qversion; - qversion.cur_version = 0x4; - qversion.least_version = 0x1; - bResult = DeviceIoControl(m_hVM, - HAX_VM_IOCTL_NOTIFY_QEMU_VERSION, - &qversion, sizeof(qversion), - NULL, 0, - &returnSize, - (LPOVERLAPPED)NULL); - - m_fastMMIO = bResult; - } - - return HXVMS_SUCCESS; -} - -HaxmVMStatus HaxmVM::AllocateMemory(void *memoryBlock, uint32_t memorySize, uint64_t basePhysicalAddress, HaxmVMMemoryType memoryType) { - // Memory block must be aligned to 4 KB pages - if (((uint64_t)memoryBlock) & 0xFFF) { - return HXVMS_MEM_MISALIGNED; - } - - // Memory size must be aligned to 4 KB pages - if (memorySize & 0xFFF) { - return HXVMS_MEMSIZE_MISALIGNED; - } - - DWORD returnSize; - BOOLEAN bResult; - - // Allocate memory - struct hax_alloc_ram_info memInfo; - memInfo.va = (uint64_t)memoryBlock; - memInfo.size = memorySize; - bResult = DeviceIoControl(m_hVM, - HAX_VM_IOCTL_ALLOC_RAM, - &memInfo, sizeof(memInfo), - NULL, 0, - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - m_lastError = GetLastError(); - return HXVMS_ALLOC_MEM_FAILED; - } - - // Configure memory - struct hax_set_ram_info setMemInfo; - setMemInfo.pa_start = basePhysicalAddress; - setMemInfo.va = (uint64_t)memoryBlock; - setMemInfo.size = memorySize; - switch (memoryType) { - case HXVM_MEM_RAM: setMemInfo.flags = 0; break; - case HXVM_MEM_ROM: setMemInfo.flags = HAX_RAM_INFO_ROM; break; - } - - bResult = DeviceIoControl(m_hVM, - HAX_VM_IOCTL_SET_RAM, - &setMemInfo, sizeof(setMemInfo), - NULL, 0, - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - m_lastError = GetLastError(); - return HXVMS_SET_MEM_FAILED; - } - - return HXVMS_SUCCESS; -} - -HaxmVMStatus HaxmVM::AllocateMemory64(void *memoryBlock, uint64_t memorySize, uint64_t basePhysicalAddress, HaxmVMMemoryType memoryType) { - // HAXM module must support 64-bit memory operations - if ((m_haxm.GetCapabilities()->winfo & HAX_CAP_64BIT_SETRAM) == 0) { - return HXVMS_UNSUPPORTED; - } - - // Memory block must be aligned to 4 KB pages - if (((uint64_t)memoryBlock) & 0xFFF) { - return HXVMS_MEM_MISALIGNED; - } - - // Memory size must be aligned to 4 KB pages - if (memorySize & 0xFFF) { - return HXVMS_MEMSIZE_MISALIGNED; - } - - DWORD returnSize; - BOOLEAN bResult; - - // Allocate memory - struct hax_ramblock_info memInfo; - memInfo.start_va = (uint64_t)memoryBlock; - memInfo.size = memorySize; - memInfo.reserved = 0; - bResult = DeviceIoControl(m_hVM, - HAX_VM_IOCTL_ADD_RAMBLOCK, - &memInfo, sizeof(memInfo), - NULL, 0, - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - m_lastError = GetLastError(); - return HXVMS_ALLOC_MEM_FAILED; - } - - // Configure memory - struct hax_set_ram_info2 setMemInfo; - setMemInfo.pa_start = basePhysicalAddress; - setMemInfo.va = (uint64_t)memoryBlock; - setMemInfo.size = memorySize; - setMemInfo.reserved1 = setMemInfo.reserved2 = 0; - switch (memoryType) { - case HXVM_MEM_RAM: setMemInfo.flags = 0; break; - case HXVM_MEM_ROM: setMemInfo.flags = HAX_RAM_INFO_ROM; break; - } - - bResult = DeviceIoControl(m_hVM, - HAX_VM_IOCTL_SET_RAM2, - &setMemInfo, sizeof(setMemInfo), - NULL, 0, - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - m_lastError = GetLastError(); - return HXVMS_SET_MEM_FAILED; - } - - return HXVMS_SUCCESS; -} - -HaxmVMStatus HaxmVM::FreeMemory(uint64_t basePhysicalAddress, uint32_t size) { - // HAXM API version must be 4 or greater to support this operation - if (m_haxm.GetModuleVersion()->cur_version < 4) { - return HXVMS_UNSUPPORTED; - } - - DWORD returnSize; - BOOLEAN bResult; - - struct hax_set_ram_info setMemInfo; - setMemInfo.pa_start = basePhysicalAddress; - setMemInfo.va = 0; - setMemInfo.size = size; - setMemInfo.flags = HAX_RAM_INFO_INVALID; - - bResult = DeviceIoControl(m_hVM, - HAX_VM_IOCTL_SET_RAM, - &setMemInfo, sizeof(setMemInfo), - NULL, 0, - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - m_lastError = GetLastError(); - return HXVMS_FREE_MEM_FAILED; - } - - return HXVMS_SUCCESS; -} - -HaxmVMStatus HaxmVM::FreeMemory64(uint64_t basePhysicalAddress, uint64_t size) { - // HAXM module must support 64-bit memory operations - if ((m_haxm.GetCapabilities()->winfo & HAX_CAP_64BIT_SETRAM) == 0) { - return HXVMS_UNSUPPORTED; - } - - DWORD returnSize; - BOOLEAN bResult; - - struct hax_set_ram_info2 setMemInfo; - setMemInfo.pa_start = basePhysicalAddress; - setMemInfo.va = 0; - setMemInfo.size = size; - setMemInfo.reserved1 = setMemInfo.reserved2 = 0; - setMemInfo.flags = HAX_RAM_INFO_INVALID; - - bResult = DeviceIoControl(m_hVM, - HAX_VM_IOCTL_SET_RAM2, - &setMemInfo, sizeof(setMemInfo), - NULL, 0, - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - m_lastError = GetLastError(); - return HXVMS_FREE_MEM_FAILED; - } - - return HXVMS_SUCCESS; -} - -HaxmVCPUStatus HaxmVM::CreateVCPU(HaxmVCPU **vcpu) { - *vcpu = new HaxmVCPU(*this, m_nextVCPUID++); - HaxmVCPUStatus status = (*vcpu)->Initialize(); - if (status != HXS_SUCCESS) { - m_lastError = GetLastError(); - delete *vcpu; - *vcpu = nullptr; - } - else { - m_vcpus.push_back(*vcpu); - } - return status; -} - -HaxmVCPUStatus HaxmVM::FreeVCPU(HaxmVCPU **vcpu) { - for (auto it = m_vcpus.begin(); it != m_vcpus.end(); it++) { - if (*it == *vcpu) { - (*vcpu)->Close(); - m_vcpus.erase(it); - delete *vcpu; - *vcpu = nullptr; - return HXVCPUS_SUCCESS; - } - } - - return HXVCPUS_FAILED; -} - -HaxmVMStatus HaxmVM::Close() { - if (m_hVM != INVALID_HANDLE_VALUE) { - // Close VCPUs - for (auto it = m_vcpus.begin(); it != m_vcpus.end(); it++) { - (*it)->Close(); - delete (*it); - } - m_vcpus.clear(); - - CloseHandle(m_hVM); - m_hVM = INVALID_HANDLE_VALUE; - } - - return HXVMS_SUCCESS; -} - -// ---------------------------------------------------------------------------- - -HaxmVCPU::HaxmVCPU(HaxmVM& vm, uint32_t id) - : m_vm(vm) - , m_vcpuID(id) - , m_tunnel(nullptr) - , m_ioTunnel(nullptr) - , m_hVCPU(INVALID_HANDLE_VALUE) - , m_lastError(ERROR_SUCCESS) - , m_debug({ 0 }) -{ -} - -HaxmVCPU::~HaxmVCPU() { -} - -HaxmVCPUStatus HaxmVCPU::Initialize() { - DWORD returnSize; - BOOLEAN bResult; - - // Create VCPU - bResult = DeviceIoControl(m_vm.Handle(), - HAX_VM_IOCTL_VCPU_CREATE, - &m_vcpuID, sizeof(m_vcpuID), - NULL, 0, - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - m_lastError = GetLastError(); - return HXVCPUS_CREATE_FAILED; - } - - // Open VCPU object - wchar_t vcpuName[20]; - swprintf_s(vcpuName, L"\\\\.\\hax_vm%02d_vcpu%02d", m_vm.ID(), m_vcpuID); - m_hVCPU = CreateFileW(vcpuName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (m_hVCPU == INVALID_HANDLE_VALUE) { - m_lastError = GetLastError(); - Close(); - return HXVCPUS_CREATE_FAILED; - } - - // Setup tunnel - struct hax_tunnel_info tunnelInfo; - bResult = DeviceIoControl(m_hVCPU, - HAX_VCPU_IOCTL_SETUP_TUNNEL, - NULL, 0, - &tunnelInfo, sizeof(tunnelInfo), - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - m_lastError = GetLastError(); - Close(); - return HXVCPUS_TUNNEL_SETUP_FAILED; - } - - m_tunnel = (struct hax_tunnel *)(intptr_t)tunnelInfo.va; - m_ioTunnel = (unsigned char *)(intptr_t)tunnelInfo.io_va; - - return HXVCPUS_SUCCESS; -} - -HaxmVCPUStatus HaxmVCPU::GetRegisters(struct vcpu_state_t *registers) { - DWORD returnSize; - BOOLEAN bResult; - - bResult = DeviceIoControl(m_hVCPU, - HAX_VCPU_GET_REGS, - NULL, 0, - registers, sizeof(struct vcpu_state_t), - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - m_lastError = GetLastError(); - return HXVCPUS_FAILED; - } - - return HXVCPUS_SUCCESS; -} - -HaxmVCPUStatus HaxmVCPU::SetRegisters(struct vcpu_state_t *registers) { - DWORD returnSize; - BOOLEAN bResult; - - bResult = DeviceIoControl(m_hVCPU, - HAX_VCPU_SET_REGS, - registers, sizeof(struct vcpu_state_t), - NULL, 0, - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - m_lastError = GetLastError(); - return HXVCPUS_FAILED; - } - - return HXVCPUS_SUCCESS; -} - -HaxmVCPUStatus HaxmVCPU::GetFPURegisters(struct fx_layout *registers) { - DWORD returnSize; - BOOLEAN bResult; - - bResult = DeviceIoControl(m_hVCPU, - HAX_VCPU_IOCTL_GET_FPU, - NULL, 0, - registers, sizeof(struct fx_layout), - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - m_lastError = GetLastError(); - return HXVCPUS_FAILED; - } - - return HXVCPUS_SUCCESS; -} - -HaxmVCPUStatus HaxmVCPU::SetFPURegisters(struct fx_layout *registers) { - DWORD returnSize; - BOOLEAN bResult; - - bResult = DeviceIoControl(m_hVCPU, - HAX_VCPU_IOCTL_SET_FPU, - registers, sizeof(struct fx_layout), - NULL, 0, - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - m_lastError = GetLastError(); - return HXVCPUS_FAILED; - } - - return HXVCPUS_SUCCESS; -} - -HaxmVCPUStatus HaxmVCPU::GetMSRs(struct hax_msr_data *msrData) { - DWORD returnSize; - BOOLEAN bResult; - - bResult = DeviceIoControl(m_hVCPU, - HAX_VCPU_IOCTL_GET_MSRS, - msrData, sizeof(struct hax_msr_data), - msrData, sizeof(struct hax_msr_data), - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - m_lastError = GetLastError(); - return HXVCPUS_FAILED; - } - - return HXVCPUS_SUCCESS; -} - -HaxmVCPUStatus HaxmVCPU::SetMSRs(struct hax_msr_data *msrData) { - DWORD returnSize; - BOOLEAN bResult; - - bResult = DeviceIoControl(m_hVCPU, - HAX_VCPU_IOCTL_SET_MSRS, - msrData, sizeof(struct hax_msr_data), - msrData, sizeof(struct hax_msr_data), - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - m_lastError = GetLastError(); - return HXVCPUS_FAILED; - } - - return HXVCPUS_SUCCESS; -} - -HaxmVCPUStatus HaxmVCPU::Run() { - DWORD returnSize; - BOOLEAN bResult; - - bResult = DeviceIoControl(m_hVCPU, - HAX_VCPU_IOCTL_RUN, - NULL, 0, - NULL, 0, - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - m_lastError = GetLastError(); - return HXVCPUS_FAILED; - } - - return HXVCPUS_SUCCESS; -} - -HaxmVCPUStatus HaxmVCPU::Step() { - m_debug.control |= HAX_DEBUG_STEP; - if (!SetDebug()) { - m_lastError = GetLastError(); - return HXVCPUS_SINGLE_STEP_FAILED; - } - - HaxmVCPUStatus status = Run(); - - m_debug.control &= ~HAX_DEBUG_STEP; - if (!SetDebug()) { - m_lastError = GetLastError(); - return HXVCPUS_SINGLE_STEP_FAILED; - } - - return status; -} - -HaxmVCPUStatus HaxmVCPU::EnableSoftwareBreakpoints(bool enable) { - if (enable) { - m_debug.control |= HAX_DEBUG_USE_SW_BP; - } - else { - m_debug.control &= ~HAX_DEBUG_USE_SW_BP; - } - - if (!SetDebug()) { - m_lastError = GetLastError(); - return HXVCPUS_FAILED; - } - - return HXVCPUS_SUCCESS; -} - -HaxmVCPUStatus HaxmVCPU::SetHardwareBreakpoints(HaxmHardwareBreakpoint breakpoints[4]) { - bool anyEnabled = false; - for (int i = 0; i < 4; i++) { - if (breakpoints[i].localEnable || breakpoints[i].globalEnable) { - anyEnabled = true; - break; - } - } - if (!anyEnabled) { - return ClearHardwareBreakpoints(); - } - - m_debug.control |= HAX_DEBUG_USE_HW_BP; - for (int i = 0; i < 4; i++) { - m_debug.dr[i] = breakpoints[i].address; - m_debug.dr[7] |= (uint64_t)(breakpoints[i].localEnable ? 1 : 0) << (0 + i * 2); - m_debug.dr[7] |= (uint64_t)(breakpoints[i].globalEnable ? 1 : 0) << (1 + i * 2); - m_debug.dr[7] |= (uint64_t)(breakpoints[i].trigger & 0x3) << (16 + i * 4); - m_debug.dr[7] |= (uint64_t)(breakpoints[i].length & 0x3) << (18 + i * 4); - } - - if (!SetDebug()) { - m_lastError = GetLastError(); - return HXVCPUS_FAILED; - } - - return HXVCPUS_SUCCESS; -} - -HaxmVCPUStatus HaxmVCPU::ClearHardwareBreakpoints() { - m_debug.control &= ~HAX_DEBUG_USE_HW_BP; - memset(m_debug.dr, 0, 8 * sizeof(uint64_t)); - if (!SetDebug()) { - m_lastError = GetLastError(); - return HXVCPUS_FAILED; - } - - return HXVCPUS_SUCCESS; -} - -HaxmVCPUStatus HaxmVCPU::Interrupt(uint8_t vector) { - DWORD returnSize; - BOOLEAN bResult; - - uint32_t vec32 = vector; - bResult = DeviceIoControl(m_hVCPU, - HAX_VCPU_IOCTL_INTERRUPT, - &vec32, sizeof(vec32), - NULL, 0, - &returnSize, - (LPOVERLAPPED)NULL); - if (!bResult) { - m_lastError = GetLastError(); - return HXVCPUS_FAILED; - } - - return HXVCPUS_SUCCESS; -} - -HaxmVCPUStatus HaxmVCPU::Close() { - if (m_hVCPU != INVALID_HANDLE_VALUE) { - CloseHandle(m_hVCPU); - m_hVCPU = INVALID_HANDLE_VALUE; - } - - return HXVCPUS_SUCCESS; -} - -BOOLEAN HaxmVCPU::SetDebug() { - DWORD returnSize; - - bool enable = m_debug.control & ~HAX_DEBUG_ENABLE; - if (enable) { - m_debug.control |= HAX_DEBUG_ENABLE; - } - else { - m_debug.control &= ~HAX_DEBUG_ENABLE; - } - - return DeviceIoControl(m_hVCPU, - HAX_IOCTL_VCPU_DEBUG, - &m_debug, sizeof(m_debug), - NULL, 0, - &returnSize, - (LPOVERLAPPED)NULL); -} diff --git a/src/cpu-module-haxm/haxm/haxm.h b/src/cpu-module-haxm/haxm/haxm.h deleted file mode 100644 index ed9f598..0000000 --- a/src/cpu-module-haxm/haxm/haxm.h +++ /dev/null @@ -1,185 +0,0 @@ -#pragma once - -#include "hax_interface.h" - -#include -#include - -enum HaxmStatus { - HXS_SUCCESS = 0, // HAXM module initialized and loaded successfully - HXS_NOT_FOUND = 0x80000000, // HAXM module not found - HXS_INIT_FAILED, // HAXM initialization failed - - HXS_SET_MEM_LIMIT_FAILED, // Could not set the global memory limit -}; - -enum HaxmVMStatus { - HXVMS_SUCCESS = 0, // VM created successfully or the operation completed without errors - HXVMS_UNSUPPORTED = 0x90000000, // The operation is unsupported - - HXVMS_CREATE_FAILED, // Failed to create VM - - HXVMS_MEM_MISALIGNED, // Memory block is not aligned to 4 KB pages - HXVMS_MEMSIZE_MISALIGNED, // Memory size is not aligned to 4 KB pages - HXVMS_ALLOC_MEM_FAILED, // Failed to allocate memory - HXVMS_SET_MEM_FAILED, // Failed to configure memory - HXVMS_FREE_MEM_FAILED, // Failed to free memory -}; - -enum HaxmVCPUStatus { - HXVCPUS_SUCCESS = 0, // VCPU created successfully or the operation completed without errors - - HXVCPUS_FAILED = 0xa0000000, // The operation failed - HXVCPUS_INVALID_PARAMETER, // An invalid parameter was passed - - HXVCPUS_CREATE_FAILED, // Failed to create VCPU - HXVCPUS_TUNNEL_SETUP_FAILED, // Failed to setup VCPU tunnel - - HXVCPUS_SINGLE_STEP_FAILED, // Failed to setup single stepping -}; - -enum HaxmVMMemoryType { - HXVM_MEM_RAM = 0, - HXVM_MEM_ROM, -}; - -enum HaxmHardwareBreakpointTrigger { - HXBPT_EXECUTION = 0, - HXBPT_DATA_WRITE, - HXBPT_8_BYTE_WIDE, - HXBPT_DATA_READ_WRITE, -}; - -enum HaxmHardwareBreakpointLength { - HXBPL_1_BYTE = 0, - HXBPL_2_BYTE, - HXBPL_8_BYTE, - HXBPL_4_BYTE, -}; - -struct HaxmHardwareBreakpoint { - uint64_t address; - bool localEnable; - bool globalEnable; - HaxmHardwareBreakpointTrigger trigger; - HaxmHardwareBreakpointLength length; -}; - -class HaxmVM; -class HaxmVCPU; - -class Haxm { -public: - Haxm(); - ~Haxm(); - - HaxmStatus Initialize(); - - HaxmStatus SetGlobalMemoryLimit(bool enabled, uint64_t limitMB); - - HaxmVMStatus CreateVM(HaxmVM **vm); - - const struct hax_module_version* GetModuleVersion() const { return &m_ver; } - const struct hax_capabilityinfo* GetCapabilities() const { return &m_caps; } - - const HANDLE Handle() const { return m_hHAXM; } - const DWORD GetLastError() const { return m_lastError; } -private: - HANDLE m_hHAXM; - DWORD m_lastError; - struct hax_module_version m_ver; - struct hax_capabilityinfo m_caps; - - std::vector m_vms; -}; - -class HaxmVM { -public: - HaxmVMStatus AllocateMemory(void *memoryBlock, uint32_t memorySize, uint64_t basePhysicalAddress, HaxmVMMemoryType memoryType); - HaxmVMStatus AllocateMemory64(void *memoryBlock, uint64_t memorySize, uint64_t basePhysicalAddress, HaxmVMMemoryType memoryType); - - HaxmVMStatus FreeMemory(uint64_t basePhysicalAddress, uint32_t size); - HaxmVMStatus FreeMemory64(uint64_t basePhysicalAddress, uint64_t size); - - HaxmVCPUStatus CreateVCPU(HaxmVCPU **vcpu); - HaxmVCPUStatus FreeVCPU(HaxmVCPU **vcpu); - - HaxmVMStatus Close(); - - const bool FastMMIOEnabled() const { return m_fastMMIO; } - - const uint32_t ID() const { return m_vmID; } - const HANDLE Handle() const { return m_hVM; } - const DWORD GetLastError() const { return m_lastError; } -private: - // Used internally by Haxm to initialize this object - HaxmVM(Haxm& haxm); - ~HaxmVM(); - - HaxmVMStatus Initialize(); - - bool m_fastMMIO; - uint32_t m_nextVCPUID; - - uint32_t m_vmID; - HANDLE m_hVM; - DWORD m_lastError; - - std::vector m_vcpus; - - Haxm& m_haxm; - - friend class Haxm; -}; - -class HaxmVCPU { -public: - HaxmVCPUStatus GetRegisters(struct vcpu_state_t *registers); - HaxmVCPUStatus SetRegisters(struct vcpu_state_t *registers); - - HaxmVCPUStatus GetFPURegisters(struct fx_layout *registers); - HaxmVCPUStatus SetFPURegisters(struct fx_layout *registers); - - HaxmVCPUStatus GetMSRs(struct hax_msr_data *msrData); - HaxmVCPUStatus SetMSRs(struct hax_msr_data *msrData); - - HaxmVCPUStatus Run(); - HaxmVCPUStatus Step(); - - HaxmVCPUStatus Interrupt(uint8_t vector); - - HaxmVCPUStatus EnableSoftwareBreakpoints(bool enable); - - HaxmVCPUStatus SetHardwareBreakpoints(HaxmHardwareBreakpoint breakpoints[4]); - HaxmVCPUStatus ClearHardwareBreakpoints(); - - HaxmVCPUStatus Close(); - - struct hax_tunnel* Tunnel() const { return m_tunnel; } - unsigned char* IOTunnel() const { return m_ioTunnel; } - const hax_debug_t* Debug() const { return &m_debug; } - - const uint32_t ID() const { return m_vcpuID; } - const HANDLE Handle() const { return m_hVCPU; } - const DWORD GetLastError() const { return m_lastError; } -private: - // Used internally by HaxmVM to initialize this object - HaxmVCPU(HaxmVM& vm, uint32_t id); - ~HaxmVCPU(); - - HaxmVCPUStatus Initialize(); - - BOOLEAN SetDebug(); - - struct hax_tunnel *m_tunnel; - unsigned char *m_ioTunnel; - hax_debug_t m_debug; - - uint32_t m_vcpuID; - HANDLE m_hVCPU; - DWORD m_lastError; - - HaxmVM& m_vm; - - friend class HaxmVM; -}; diff --git a/src/cpu-module-haxm/haxm/linux/hax_interface_linux.h b/src/cpu-module-haxm/haxm/linux/hax_interface_linux.h deleted file mode 100644 index 058d319..0000000 --- a/src/cpu-module-haxm/haxm/linux/hax_interface_linux.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2011 Intel Corporation - * Copyright (c) 2018 Kryptos Logic - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HAX_LINUX_HAX_INTERFACE_LINUX_H_ -#define HAX_LINUX_HAX_INTERFACE_LINUX_H_ - -#include - -/* The mac specific interface to qemu because of mac's - * special handling like hax tunnel allocation etc */ -/* HAX model level ioctl */ -#define HAX_IOCTL_VERSION _IOWR(0, 0x20, struct hax_module_version) -#define HAX_IOCTL_CREATE_VM _IOWR(0, 0x21, uint32_t) -#define HAX_IOCTL_DESTROY_VM _IOW(0, 0x22, uint32_t) -#define HAX_IOCTL_CAPABILITY _IOR(0, 0x23, struct hax_capabilityinfo) -#define HAX_IOCTL_SET_MEMLIMIT _IOWR(0, 0x24, struct hax_set_memlimit) - -// Only for backward compatibility with old Qemu. -#define HAX_VM_IOCTL_VCPU_CREATE_ORIG _IOR(0, 0x80, int) - -#define HAX_VM_IOCTL_VCPU_CREATE _IOWR(0, 0x80, uint32_t) -#define HAX_VM_IOCTL_ALLOC_RAM _IOWR(0, 0x81, struct hax_alloc_ram_info) -#define HAX_VM_IOCTL_SET_RAM _IOWR(0, 0x82, struct hax_set_ram_info) -#define HAX_VM_IOCTL_VCPU_DESTROY _IOR(0, 0x83, uint32_t) -#define HAX_VM_IOCTL_ADD_RAMBLOCK _IOW(0, 0x85, struct hax_ramblock_info) -#define HAX_VM_IOCTL_SET_RAM2 _IOWR(0, 0x86, struct hax_set_ram_info2) -#define HAX_VM_IOCTL_PROTECT_RAM _IOWR(0, 0x87, struct hax_protect_ram_info) - -#define HAX_VCPU_IOCTL_RUN _IO(0, 0xc0) -#define HAX_VCPU_IOCTL_SET_MSRS _IOWR(0, 0xc1, struct hax_msr_data) -#define HAX_VCPU_IOCTL_GET_MSRS _IOWR(0, 0xc2, struct hax_msr_data) - -#define HAX_VCPU_IOCTL_SET_FPU _IOW(0, 0xc3, struct fx_layout) -#define HAX_VCPU_IOCTL_GET_FPU _IOR(0, 0xc4, struct fx_layout) - -#define HAX_VCPU_IOCTL_SETUP_TUNNEL _IOWR(0, 0xc5, struct hax_tunnel_info) -#define HAX_VCPU_IOCTL_INTERRUPT _IOWR(0, 0xc6, uint32_t) -#define HAX_VCPU_SET_REGS _IOWR(0, 0xc7, struct vcpu_state_t) -#define HAX_VCPU_GET_REGS _IOWR(0, 0xc8, struct vcpu_state_t) - -/* API 2.0 */ -#define HAX_VM_IOCTL_NOTIFY_QEMU_VERSION _IOW(0, 0x84, struct hax_qemu_version) - -#define HAX_IOCTL_VCPU_DEBUG _IOW(0, 0xc9, struct hax_debug_t) - - -#endif // HAX_LINUX_HAX_INTERFACE_LINUX_H_ diff --git a/src/cpu-module-haxm/haxm/linux/hax_types_linux.h b/src/cpu-module-haxm/haxm/linux/hax_types_linux.h deleted file mode 100644 index 0bca476..0000000 --- a/src/cpu-module-haxm/haxm/linux/hax_types_linux.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2011 Intel Corporation - * Copyright (c) 2018 Kryptos Logic - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HAX_LINUX_HAX_TYPES_LINUX_H_ -#define HAX_LINUX_HAX_TYPES_LINUX_H_ - -#include - -// Signed Types -typedef int8_t int8; -typedef int16_t int16; -typedef int32_t int32; -typedef int64_t int64; - -// Unsigned Types -typedef uint8_t uint8; -typedef uint16_t uint16; -typedef uint32_t uint32; -typedef uint64_t uint64; - -typedef unsigned int uint; -typedef unsigned long ulong; -typedef unsigned long ulong_t; - -#if defined(__i386__) -typedef uint32_t mword; -#endif -#if defined (__x86_64__) -typedef uint64_t mword; -#endif - -#endif // HAX_LINUX_HAX_TYPES_LINUX_H_ diff --git a/src/cpu-module-haxm/haxm/vcpu_state.h b/src/cpu-module-haxm/haxm/vcpu_state.h deleted file mode 100644 index 17d72f1..0000000 --- a/src/cpu-module-haxm/haxm/vcpu_state.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2004-2010 Intel Corporation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HAX_VCPU_STATE_H_ -#define HAX_VCPU_STATE_H_ - -union interruptibility_state_t { - uint32_t raw; - struct { - uint32_t sti_blocking : 1; - uint32_t movss_blocking : 1; - uint32_t smi_blocking : 1; - uint32_t nmi_blocking : 1; - uint32_t reserved : 28; - }; - uint64_t pad; -} PACKED; - -typedef union interruptibility_state_t interruptibility_state_t; - -// Segment descriptor -struct segment_desc_t { - uint16_t selector; - uint16_t _dummy; - uint32_t limit; - uint64_t base; - union { - struct { - uint32_t type : 4; - uint32_t desc : 1; - uint32_t dpl : 2; - uint32_t present : 1; - uint32_t : 4; - uint32_t available : 1; - uint32_t long_mode : 1; - uint32_t operand_size : 1; - uint32_t granularity : 1; - uint32_t null : 1; - uint32_t : 15; - }; - uint32_t ar; - }; - uint32_t ipad; -} PACKED; - -typedef struct segment_desc_t segment_desc_t; - -struct vcpu_state_t { - union { - uint64_t _regs[16]; - struct { - union { - struct { - uint8_t _al, - _ah; - }; - uint16_t _ax; - uint32_t _eax; - uint64_t _rax; - }; - union { - struct { - uint8_t _cl, - _ch; - }; - uint16_t _cx; - uint32_t _ecx; - uint64_t _rcx; - }; - union { - struct { - uint8_t _dl, - _dh; - }; - uint16_t _dx; - uint32_t _edx; - uint64_t _rdx; - }; - union { - struct { - uint8_t _bl, - _bh; - }; - uint16_t _bx; - uint32_t _ebx; - uint64_t _rbx; - }; - union { - uint16_t _sp; - uint32_t _esp; - uint64_t _rsp; - }; - union { - uint16_t _bp; - uint32_t _ebp; - uint64_t _rbp; - }; - union { - uint16_t _si; - uint32_t _esi; - uint64_t _rsi; - }; - union { - uint16_t _di; - uint32_t _edi; - uint64_t _rdi; - }; - - uint64_t _r8; - uint64_t _r9; - uint64_t _r10; - uint64_t _r11; - uint64_t _r12; - uint64_t _r13; - uint64_t _r14; - uint64_t _r15; - }; - }; - - union { - uint32_t _eip; - uint64_t _rip; - }; - - union { - uint32_t _eflags; - uint64_t _rflags; - }; - - segment_desc_t _cs; - segment_desc_t _ss; - segment_desc_t _ds; - segment_desc_t _es; - segment_desc_t _fs; - segment_desc_t _gs; - segment_desc_t _ldt; - segment_desc_t _tr; - - segment_desc_t _gdt; - segment_desc_t _idt; - - uint64_t _cr0; - uint64_t _cr2; - uint64_t _cr3; - uint64_t _cr4; - - uint64_t _dr0; - uint64_t _dr1; - uint64_t _dr2; - uint64_t _dr3; - uint64_t _dr6; - uint64_t _dr7; - uint64_t _pde; - - uint32_t _efer; - - uint32_t _sysenter_cs; - uint64_t _sysenter_eip; - uint64_t _sysenter_esp; - - uint32_t _activity_state; - uint32_t pad; - interruptibility_state_t _interruptibility_state; -} PACKED; - -#endif // HAX_VCPU_STATE_H_ diff --git a/src/cpu-module-haxm/haxm/windows/hax_interface_windows.h b/src/cpu-module-haxm/haxm/windows/hax_interface_windows.h deleted file mode 100644 index 4f7a93e..0000000 --- a/src/cpu-module-haxm/haxm/windows/hax_interface_windows.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2011 Intel Corporation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HAX_WINDOWS_HAX_INTERFACE_WINDOWS_H_ -#define HAX_WINDOWS_HAX_INTERFACE_WINDOWS_H_ - -#ifndef CTL_CODE -#define CTL_CODE( DeviceType, Function, Method, Access ) ( \ - ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ -) -#endif - -#define HAX_DEVICE_TYPE 0x4000 - -#define HAX_IOCTL_VERSION \ - CTL_CODE(HAX_DEVICE_TYPE, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_IOCTL_CREATE_VM \ - CTL_CODE(HAX_DEVICE_TYPE, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_IOCTL_CAPABILITY \ - CTL_CODE(HAX_DEVICE_TYPE, 0x910, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_IOCTL_SET_MEMLIMIT \ - CTL_CODE(HAX_DEVICE_TYPE, 0x911, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define HAX_VM_IOCTL_VCPU_CREATE \ - CTL_CODE(HAX_DEVICE_TYPE, 0x902, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VM_IOCTL_ALLOC_RAM \ - CTL_CODE(HAX_DEVICE_TYPE, 0x903, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VM_IOCTL_SET_RAM \ - CTL_CODE(HAX_DEVICE_TYPE, 0x904, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VM_IOCTL_VCPU_DESTROY \ - CTL_CODE(HAX_DEVICE_TYPE, 0x905, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VM_IOCTL_ADD_RAMBLOCK \ - CTL_CODE(HAX_DEVICE_TYPE, 0x913, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VM_IOCTL_SET_RAM2 \ - CTL_CODE(HAX_DEVICE_TYPE, 0x914, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VM_IOCTL_PROTECT_RAM \ - CTL_CODE(HAX_DEVICE_TYPE, 0x915, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define HAX_VCPU_IOCTL_RUN \ - CTL_CODE(HAX_DEVICE_TYPE, 0x906, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VCPU_IOCTL_SET_MSRS \ - CTL_CODE(HAX_DEVICE_TYPE, 0x907, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VCPU_IOCTL_GET_MSRS \ - CTL_CODE(HAX_DEVICE_TYPE, 0x908, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define HAX_VCPU_IOCTL_SET_FPU \ - CTL_CODE(HAX_DEVICE_TYPE, 0x909, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VCPU_IOCTL_GET_FPU \ - CTL_CODE(HAX_DEVICE_TYPE, 0x90a, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define HAX_VCPU_IOCTL_SETUP_TUNNEL \ - CTL_CODE(HAX_DEVICE_TYPE, 0x90b, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VCPU_IOCTL_INTERRUPT \ - CTL_CODE(HAX_DEVICE_TYPE, 0x90c, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VCPU_SET_REGS \ - CTL_CODE(HAX_DEVICE_TYPE, 0x90d, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VCPU_GET_REGS \ - CTL_CODE(HAX_DEVICE_TYPE, 0x90e, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VCPU_IOCTL_KICKOFF \ - CTL_CODE(HAX_DEVICE_TYPE, 0x90f, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/* API version 2.0 */ -#define HAX_VM_IOCTL_NOTIFY_QEMU_VERSION \ - CTL_CODE(HAX_DEVICE_TYPE, 0x910, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define HAX_IOCTL_VCPU_DEBUG \ - CTL_CODE(HAX_DEVICE_TYPE, 0x916, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#endif // HAX_WINDOWS_HAX_INTERFACE_WINDOWS_H_ diff --git a/src/cpu-module-haxm/haxm/windows/hax_types_windows.h b/src/cpu-module-haxm/haxm/windows/hax_types_windows.h deleted file mode 100644 index f944700..0000000 --- a/src/cpu-module-haxm/haxm/windows/hax_types_windows.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2011 Intel Corporation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HAX_WINDOWS_HAX_TYPES_WINDOWS_H_ -#define HAX_WINDOWS_HAX_TYPES_WINDOWS_H_ - -#if defined(_WIN32) && !defined(__cplusplus) -#define inline __inline -typedef unsigned char bool; -#define true 1 -#define false 0 -#endif - -// Signed Types -typedef signed char int8_t; -typedef signed short int16_t; -typedef signed int int32_t; -typedef signed long long int64_t; - -// Unsigned Types -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; -typedef unsigned int uint; -typedef unsigned long ulong; -typedef unsigned long ulong_t; - -#if defined(_X86_) -typedef uint32_t mword; -#endif - -#if defined (_AMD64_) -typedef uint64_t mword; -#endif - -#endif // HAX_WINDOWS_HAX_TYPES_WINDOWS_H_ diff --git a/src/cpu-module-kvm/CMakeLists.txt b/src/cpu-module-kvm/CMakeLists.txt deleted file mode 100644 index d12f33d..0000000 --- a/src/cpu-module-kvm/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -# Add sources -file(GLOB DIR_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/kvm/*.h - ) - -file(GLOB DIR_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/kvm/*.cpp - ) - -set(SOURCES ${SOURCES} - ${DIR_HEADERS} - ${DIR_SOURCES} - ) - - -# Export module -add_definitions(-DMODULE_EXPORTS) - -# Main Executable -add_definitions("-Wall -Werror -O0 -g") -add_library(cpu-module-kvm SHARED "${SOURCES}") -target_include_directories(cpu-module-kvm PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - -# Include common module code -target_link_libraries(cpu-module-kvm common cpu-module) - -# Copy SO to CLI output directory -string(TOLOWER ${CPU_MODULE} CPU_MODULE_LC) -if(CPU_MODULE_LC STREQUAL kvm) - add_custom_command(TARGET cpu-module-kvm - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/src/cli/modules - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/*.so ${CMAKE_BINARY_DIR}/src/cli/modules - COMMENT "Copy DLLs to target directory") -endif() - diff --git a/src/cpu-module-kvm/cpu_kvm.cpp b/src/cpu-module-kvm/cpu_kvm.cpp deleted file mode 100644 index 8c77801..0000000 --- a/src/cpu-module-kvm/cpu_kvm.cpp +++ /dev/null @@ -1,432 +0,0 @@ - -#include "cpu_kvm.h" -#include "vixen/log.h" - -#include -#include -#include -#include - -namespace vixen { -namespace cpu { - -KvmCpu::KvmCpu() { - m_kvm = nullptr; - m_vm = nullptr; - m_vcpu = nullptr; -} - -KvmCpu::~KvmCpu() { - if (m_kvm != nullptr) { - // Deleting this will automatically delete the VM and VCPU - delete m_kvm; - m_kvm = nullptr; - } -} - -CPUInitStatus KvmCpu::InitializeImpl() { - if (m_kvm == nullptr) { - m_kvm = new Kvm; - - auto status = m_kvm->Initialize(); - if (status != KVMS_SUCCESS) { - return CPUS_INIT_PLATFORM_INIT_FAILED; - } - - auto vmStatus = m_kvm->CreateVM(&m_vm); - if (vmStatus != KVMVMS_SUCCESS) { - delete m_kvm; - m_kvm = nullptr; - return CPUS_INIT_CREATE_VM_FAILED; - } - - auto vcpuStatus = m_vm->CreateVCPU(&m_vcpu); - if (vcpuStatus != KVMVCPUS_SUCCESS) { - delete m_kvm; - m_kvm = nullptr; - return CPUS_INIT_CREATE_CPU_FAILED; - } - } - - return CPUS_INIT_OK; -} - -CPUStatus KvmCpu::RunImpl() { - UpdateRegisters(); - auto status = m_vcpu->Run(); - return HandleExecResult(status); -} - -void KvmCpu::UpdateRegisters() { - // Update registers if they've been changed - if (m_regsChanged) { - m_vcpu->SetRegisters(m_regs); - m_vcpu->SetSRegisters(m_sregs); - m_regsChanged = false; - } - if (m_fpuRegsChanged) { - m_vcpu->SetFPURegisters(m_fpuRegs); - m_fpuRegsChanged = false; - } -} - -CPUStatus KvmCpu::HandleExecResult(KvmVCPUStatus status) { - // Mark the registers as dirty - m_regsDirty = true; - m_fpuRegsDirty = true; - - // Check VM status - if (status == KVMVCPUS_RUN_FAILED) { - return CPUS_FAILED; - } - - auto kvmRun = m_vcpu->kvmRun(); - - // Handle exit status using tunnel - switch (kvmRun->exit_reason) { - case KVM_EXIT_HLT: m_exitInfo.reason = CPU_EXIT_HLT; break; - case KVM_EXIT_IO: m_exitInfo.reason = CPU_EXIT_NORMAL; - HandleIO(kvmRun->io.direction, kvmRun->io.port, kvmRun->io.size, kvmRun->io.count, kvmRun->io.data_offset); - break; - case KVM_EXIT_MMIO: m_exitInfo.reason = CPU_EXIT_NORMAL; - HandleMMIO((uint32_t)kvmRun->mmio.phys_addr, (uint32_t*)kvmRun->mmio.data, (uint8_t)kvmRun->mmio.len, kvmRun->mmio.is_write); - break; - case KVM_EXIT_INTR: m_exitInfo.reason = CPU_EXIT_NORMAL; break; - case KVM_EXIT_FAIL_ENTRY: m_exitInfo.reason = CPU_EXIT_SHUTDOWN; - log_error("KVM_EXIT_FAIL_ENTRY. Failure reason: 0x%X\n", m_vcpu->kvmRun()->fail_entry.hardware_entry_failure_reason); - break; - } - - return CPUS_OK; -} - - -InterruptResult KvmCpu::InterruptImpl(uint8_t vector) { - return INTR_SUCCESS; -} - -CPUMemMapStatus KvmCpu::MemMapSubregion(MemoryRegion *subregion) { - log_debug("KvmCpu: Mapping 0x%X bytes to guest memory address 0x%X\n", subregion->m_size, subregion->m_start); - - switch (subregion->m_type) { - case MEM_REGION_MMIO: - { - // Do nothing - KVM treats all unmapped memory as MMIO - return CPUS_MMAP_OK; - } - - case MEM_REGION_NONE: - { - // Shouldn't happen - assert(0); - return CPUS_MMAP_INVALID_TYPE; - } - - case MEM_REGION_RAM: - case MEM_REGION_ROM: - { - auto status = m_vm->MapUserMemoryToGuest(subregion->m_data, subregion->m_size, subregion->m_start); - switch (status) { - case KVMVMS_SUCCESS: return CPUS_MMAP_OK; - case KVMVMS_MEM_MISALIGNED: return CPUS_MMAP_MEMORY_ADDR_MISALIGNED; - case KVMVMS_MEMSIZE_MISALIGNED: return CPUS_MMAP_MEMORY_SIZE_MISALIGNED; - case KVMVMS_MEM_ERROR: return CPUS_MMAP_MAPPING_FAILED; - return CPUS_MMAP_UNHANDLED_ERROR; - case KVMVMS_CREATE_FAILED: - // Shouldn't happen - return CPUS_MMAP_UNHANDLED_ERROR; - } - } - default: - // Shouldn't happen - return CPUS_MMAP_INVALID_TYPE; - } -} - -#define REFRESH_REGISTERS do { \ - auto status = RefreshRegisters(false); \ - if (status) { \ - return status; \ - } \ -} while (0) - -CPUOperationStatus KvmCpu::RegRead(enum CpuReg reg, uint32_t *value) { - REFRESH_REGISTERS; - - switch (reg) { - case REG_EIP: *value = (uint32_t)m_regs.rip; break; - case REG_EFLAGS: *value = (uint32_t)m_regs.rflags; break; - case REG_EAX: *value = (uint32_t)m_regs.rax; break; - case REG_ECX: *value = (uint32_t)m_regs.rcx; break; - case REG_EDX: *value = (uint32_t)m_regs.rdx; break; - case REG_EBX: *value = (uint32_t)m_regs.rbx; break; - case REG_ESI: *value = (uint32_t)m_regs.rsi; break; - case REG_EDI: *value = (uint32_t)m_regs.rdi; break; - case REG_ESP: *value = (uint32_t)m_regs.rsp; break; - case REG_EBP: *value = (uint32_t)m_regs.rbp; break; - case REG_CS: *value = m_sregs.cs.selector; break; - case REG_SS: *value = m_sregs.ss.selector; break; - case REG_DS: *value = m_sregs.ds.selector; break; - case REG_ES: *value = m_sregs.es.selector; break; - case REG_FS: *value = m_sregs.fs.selector; break; - case REG_GS: *value = m_sregs.gs.selector; break; - case REG_TR: *value = m_sregs.tr.selector; break; - case REG_CR0: *value = (uint32_t)m_sregs.cr0; break; - case REG_CR2: *value = (uint32_t)m_sregs.cr2; break; - case REG_CR3: *value = (uint32_t)m_sregs.cr3; break; - case REG_CR4: *value = (uint32_t)m_sregs.cr4; break; - default: return CPUS_OP_INVALID_REGISTER; - } - - return CPUS_OP_OK; -} - -CPUOperationStatus KvmCpu::RegWrite(enum CpuReg reg, uint32_t value) { - REFRESH_REGISTERS; - - switch (reg) { - case REG_EIP: m_regs.rip = value; break; - case REG_EFLAGS: m_regs.rflags = value; break; - case REG_EAX: m_regs.rax = value; break; - case REG_ECX: m_regs.rcx = value; break; - case REG_EDX: m_regs.rdx = value; break; - case REG_EBX: m_regs.rbx = value; break; - case REG_ESI: m_regs.rsi = value; break; - case REG_EDI: m_regs.rdi = value; break; - case REG_ESP: m_regs.rsp = value; break; - case REG_EBP: m_regs.rbp = value; break; - case REG_CS: LoadSegmentSelector((uint16_t)value, &m_sregs.cs); break; - case REG_SS: LoadSegmentSelector((uint16_t)value, &m_sregs.ss); break; - case REG_DS: LoadSegmentSelector((uint16_t)value, &m_sregs.ds); break; - case REG_ES: LoadSegmentSelector((uint16_t)value, &m_sregs.es); break; - case REG_FS: LoadSegmentSelector((uint16_t)value, &m_sregs.fs); break; - case REG_GS: LoadSegmentSelector((uint16_t)value, &m_sregs.gs); break; - case REG_TR: LoadSegmentSelector((uint16_t)value, &m_sregs.tr); break; - case REG_CR0: m_sregs.cr0 = value; break; - case REG_CR2: m_sregs.cr2 = value; break; - case REG_CR3: m_sregs.cr3 = value; break; - case REG_CR4: m_sregs.cr4 = value; break; - default: return CPUS_OP_INVALID_REGISTER; - } - - m_regsChanged = true; - - return CPUS_OP_OK; -} - -CPUOperationStatus KvmCpu::RegRead(CpuReg regs[], uint32_t values[], uint8_t numRegs) { - REFRESH_REGISTERS; - - for (uint8_t i = 0; i < numRegs; i++) { - switch (regs[i]) { - case REG_EIP: values[i] = (uint32_t)m_regs.rip; break; - case REG_EFLAGS: values[i] = (uint32_t)m_regs.rflags; break; - case REG_EAX: values[i] = (uint32_t)m_regs.rax; break; - case REG_ECX: values[i] = (uint32_t)m_regs.rcx; break; - case REG_EDX: values[i] = (uint32_t)m_regs.rdx; break; - case REG_EBX: values[i] = (uint32_t)m_regs.rbx; break; - case REG_ESI: values[i] = (uint32_t)m_regs.rsi; break; - case REG_EDI: values[i] = (uint32_t)m_regs.rdi; break; - case REG_ESP: values[i] = (uint32_t)m_regs.rsp; break; - case REG_EBP: values[i] = (uint32_t)m_regs.rbp; break; - case REG_CS: values[i] = m_sregs.cs.selector; break; - case REG_SS: values[i] = m_sregs.ss.selector; break; - case REG_DS: values[i] = m_sregs.ds.selector; break; - case REG_ES: values[i] = m_sregs.es.selector; break; - case REG_FS: values[i] = m_sregs.fs.selector; break; - case REG_GS: values[i] = m_sregs.gs.selector; break; - case REG_TR: values[i] = m_sregs.tr.selector; break; - case REG_CR0: values[i] = (uint32_t)m_sregs.cr0; break; - case REG_CR2: values[i] = (uint32_t)m_sregs.cr2; break; - case REG_CR3: values[i] = (uint32_t)m_sregs.cr3; break; - case REG_CR4: values[i] = (uint32_t)m_sregs.cr4; break; - default: return CPUS_OP_INVALID_REGISTER; - } - } - - return CPUS_OP_OK; -} - -CPUOperationStatus KvmCpu::RegWrite(CpuReg regs[], uint32_t values[], uint8_t numRegs) { - REFRESH_REGISTERS; - - for (uint8_t i = 0; i < numRegs; i++) { - switch (regs[i]) { - case REG_EIP: m_regs.rip = values[i]; break; - case REG_EFLAGS: m_regs.rflags = values[i]; break; - case REG_EAX: m_regs.rax = values[i]; break; - case REG_ECX: m_regs.rcx = values[i]; break; - case REG_EDX: m_regs.rdx = values[i]; break; - case REG_EBX: m_regs.rbx = values[i]; break; - case REG_ESI: m_regs.rsi = values[i]; break; - case REG_EDI: m_regs.rdi = values[i]; break; - case REG_ESP: m_regs.rsp = values[i]; break; - case REG_EBP: m_regs.rbp = values[i]; break; - case REG_CS: LoadSegmentSelector((uint16_t)values[i], &m_sregs.cs); break; - case REG_SS: LoadSegmentSelector((uint16_t)values[i], &m_sregs.ss); break; - case REG_DS: LoadSegmentSelector((uint16_t)values[i], &m_sregs.ds); break; - case REG_ES: LoadSegmentSelector((uint16_t)values[i], &m_sregs.es); break; - case REG_FS: LoadSegmentSelector((uint16_t)values[i], &m_sregs.fs); break; - case REG_GS: LoadSegmentSelector((uint16_t)values[i], &m_sregs.gs); break; - case REG_TR: LoadSegmentSelector((uint16_t)values[i], &m_sregs.tr); break; - case REG_CR0: m_sregs.cr0 = values[i]; break; - case REG_CR2: m_sregs.cr2 = values[i]; break; - case REG_CR3: m_sregs.cr3 = values[i]; break; - case REG_CR4: m_sregs.cr4 = values[i]; break; - default: return CPUS_OP_INVALID_REGISTER; - } - } - - m_regsChanged = true; - - return CPUS_OP_OK; -} - -CPUOperationStatus KvmCpu::GetGDT(uint32_t *addr, uint32_t *size) { - REFRESH_REGISTERS; - - *addr = (uint32_t)m_sregs.gdt.base; - *size = m_sregs.gdt.limit; - - return CPUS_OP_OK; -} - -CPUOperationStatus KvmCpu::SetGDT(uint32_t addr, uint32_t size) { - REFRESH_REGISTERS; - - m_sregs.gdt.base = addr; - m_sregs.gdt.limit = size; - - m_regsChanged = true; - - return CPUS_OP_OK; -} - -CPUOperationStatus KvmCpu::GetIDT(uint32_t *addr, uint32_t *size) { - REFRESH_REGISTERS; - - *addr = (uint32_t)m_sregs.idt.base; - *size = m_sregs.idt.limit; - return CPUS_OP_OK; -} - -CPUOperationStatus KvmCpu::SetIDT(uint32_t addr, uint32_t size) { - REFRESH_REGISTERS; - - m_sregs.idt.base = addr; - m_sregs.idt.limit = size; - - m_regsChanged = true; - - return CPUS_OP_OK; -} - -CPUStatus KvmCpu::HandleIO(uint8_t direction, uint16_t port, uint8_t size, uint32_t count, uint64_t dataOffset) { - uint8_t *ptr; - if (direction) { - ptr = (uint8_t*)((((uint64_t)m_vcpu->kvmRun()) + dataOffset) + size * count - size); - } - else { - ptr = (uint8_t*)(((uint64_t)m_vcpu->kvmRun()) + dataOffset); - } - - for (uint16_t i = 0; i < count; i++) { - if (direction == KVM_EXIT_IO_OUT) { - uint32_t value; - switch (size) { - case 1: value = *ptr; break; - case 2: value = *reinterpret_cast(ptr); break; - case 4: value = *reinterpret_cast(ptr); break; - default: assert(0); - } - m_ioMapper->IOWrite(port, value, size); - } - else { - m_ioMapper->IORead(port, (uint32_t*)ptr, size); - } - - if (direction) { - ptr -= size; - } - else { - ptr += size; - } - } - return CPUS_OK; -} - -CPUStatus KvmCpu::HandleMMIO(uint32_t physAddress, uint32_t *data, uint8_t size, uint8_t isWrite) { - if (isWrite) { - m_ioMapper->MMIOWrite(physAddress, *data, size); - } - else { - m_ioMapper->MMIORead(physAddress, data, size); - } - return CPUS_OK; -} - -CPUOperationStatus KvmCpu::RefreshRegisters(bool refreshFPU) { - if (m_regsDirty) { - auto regStatus = m_vcpu->GetRegisters(&m_regs); - auto sRegStatus = m_vcpu->GetSRegisters(&m_sregs); - - if ((regStatus != KVMVCPUS_SUCCESS) || - (sRegStatus != KVMVCPUS_SUCCESS)) { - return CPUS_OP_FAILED; - } - - if (refreshFPU) { - m_vcpu->GetFPURegisters(&m_fpuRegs); - } - - m_regsDirty = false; - } - return CPUS_OP_OK; -} - -int KvmCpu::LoadSegmentSelector(uint16_t selector, struct kvm_segment *segment) { - segment->selector = selector; - - GDTEntry gdtEntry; - VMemRead((uint32_t)(m_sregs.gdt.base + selector), sizeof(GDTEntry), &gdtEntry); - - // Not much on this in KVM documentation. See Intel documentation for a better description. - // "Intel Software Developer's Manual Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D and 4" - // "Vol 3C - 24.4 Guest-State Area". Specifically pg. 3770 & 3771 - segment->avl = (uint8_t)(gdtEntry.data.flags & 0x1); //Availability - segment->l = (uint8_t)((gdtEntry.data.flags >> 1) & 0x1); //Long mode - segment->db = (uint8_t)((gdtEntry.data.flags >> 2) & 0x1); //Default operation size - segment->g = (uint8_t)(((gdtEntry.data.flags) >> 3) & 0x1); //Granularity - - segment->present = (uint8_t)((gdtEntry.data.access >> 7) & 0x1); - segment->dpl = (uint8_t)((gdtEntry.data.access >> 5) & 0x3); - segment->s = (uint8_t)((gdtEntry.data.access >> 4) & 0x1); - segment->type = (uint8_t)(gdtEntry.data.access & 0xF); - - segment->base = gdtEntry.GetBase(); - segment->limit = gdtEntry.GetLimit(); - - m_regsChanged = true; - - return 0; -} - -CPUOperationStatus KvmCpu::InjectInterrupt(uint8_t vector) { - auto status = m_vcpu->Interrupt(vector); - if (status != KVMVCPUS_SUCCESS) { - return CPUS_OP_FAILED; - } - m_vcpu->kvmRun()->request_interrupt_window = 0; - return CPUS_OP_OK; -} - -bool KvmCpu::CanInjectInterrupt() { - return m_vcpu->kvmRun()->ready_for_interrupt_injection != 0; -} - -void KvmCpu::RequestInterruptWindow() { - m_vcpu->kvmRun()->request_interrupt_window = 1; -} - -} -} diff --git a/src/cpu-module-kvm/cpu_kvm.h b/src/cpu-module-kvm/cpu_kvm.h deleted file mode 100644 index 1b8a951..0000000 --- a/src/cpu-module-kvm/cpu_kvm.h +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once - -#include "vixen/cpu.h" -#include "kvm/kvm.h" - -#include -#include -#include -#include -#include - -namespace vixen { -namespace cpu { - -class KvmCpu : public Cpu { - -public: - KvmCpu(); - ~KvmCpu(); - - CPUInitStatus InitializeImpl(); - - CPUStatus RunImpl(); - InterruptResult InterruptImpl(uint8_t vector); - - CPUMemMapStatus MemMapSubregion(MemoryRegion *subregion); - - CPUOperationStatus RegRead(enum CpuReg reg, uint32_t *value); - CPUOperationStatus RegWrite(enum CpuReg reg, uint32_t value); - - CPUOperationStatus RegRead(enum CpuReg regs[], uint32_t values[], uint8_t numRegs) override; - CPUOperationStatus RegWrite(enum CpuReg regs[], uint32_t values[], uint8_t numRegs) override; - - CPUOperationStatus GetGDT(uint32_t *addr, uint32_t *size); - CPUOperationStatus SetGDT(uint32_t addr, uint32_t size); - - CPUOperationStatus GetIDT(uint32_t *addr, uint32_t *size); - CPUOperationStatus SetIDT(uint32_t addr, uint32_t size); - -protected: - CPUOperationStatus InjectInterrupt(uint8_t vector); - bool CanInjectInterrupt(); - void RequestInterruptWindow(); - -private: - Kvm *m_kvm; - KvmVM *m_vm; - KvmVCPU *m_vcpu; - - bool m_regsDirty; - bool m_fpuRegsDirty; - bool m_regsChanged; - bool m_fpuRegsChanged; - - struct kvm_regs m_regs; - struct kvm_sregs m_sregs; - struct kvm_fpu m_fpuRegs; - - void UpdateRegisters(); - CPUStatus HandleExecResult(KvmVCPUStatus status); - - CPUStatus HandleIO(uint8_t direction, uint16_t port, uint8_t size, uint32_t count, uint64_t dataOffset); - CPUStatus HandleMMIO(uint32_t physAddress, uint32_t *data, uint8_t size, uint8_t isWrite); - - CPUOperationStatus RefreshRegisters(bool refreshFPU); - - int LoadSegmentSelector(uint16_t selector, struct kvm_segment* segment); - -}; - -} -} diff --git a/src/cpu-module-kvm/cpu_kvm_module.cpp b/src/cpu-module-kvm/cpu_kvm_module.cpp deleted file mode 100644 index 35243e1..0000000 --- a/src/cpu-module-kvm/cpu_kvm_module.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "vixen/cpu_module_decl.h" -#include "cpu_kvm_module.h" - -namespace vixen { -namespace modules { -namespace cpu { - -using namespace vixen::cpu; - -CPU_MODULE_BEGIN -CPU_MODULE_INFO(KvmCPUModule, "KVM CPU Module", "0.0.1") -CPU_MODULE_END - -Cpu *KvmCPUModule::GetCPU() { - return &m_cpu; -} - -void KvmCPUModule::FreeCPU(Cpu *cpu) { - -} - -void KvmCPUModule::Cleanup() { - -} - -} -} -} diff --git a/src/cpu-module-kvm/cpu_kvm_module.h b/src/cpu-module-kvm/cpu_kvm_module.h deleted file mode 100644 index 4b6322c..0000000 --- a/src/cpu-module-kvm/cpu_kvm_module.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "vixen/cpu.h" -#include "cpu_kvm.h" - -namespace vixen { -namespace modules { -namespace cpu { - -using namespace vixen::cpu; - -class KvmCPUModule : public ICPUModule { -public: - Cpu *GetCPU(); - void FreeCPU(Cpu *cpu); - void Cleanup(); -private: - KvmCpu m_cpu; -}; - -} -} -} diff --git a/src/cpu-module-kvm/kvm/kvm.cpp b/src/cpu-module-kvm/kvm/kvm.cpp deleted file mode 100644 index 275cdb3..0000000 --- a/src/cpu-module-kvm/kvm/kvm.cpp +++ /dev/null @@ -1,254 +0,0 @@ -#include "kvm.h" - -#include -#include -#include -#include -#include -#include - -Kvm::Kvm() { - -} - -Kvm::~Kvm() { - if(m_fd > 0) { - close(m_fd); - } -} - -KvmStatus Kvm::Initialize() { - // Open the KVM module - m_fd = open("/dev/kvm", O_RDWR); - - if(m_fd < 0) { - return KVMS_OPEN_FAILED; - } - - // Get KVM version - int kvmVersion; - - // Refuse to run if API version != 12 as per API docs recommendation. - kvmVersion = ioctl(m_fd, KVM_GET_API_VERSION, nullptr); - if(kvmVersion != 12) { - return KVMS_API_VERSION_UNSUPPORTED; - } - - // Check if have the capabilities we need. - int kvmCapResult; - - // User mem to VM mapping. - kvmCapResult = ioctl(m_fd, KVM_CHECK_EXTENSION, KVM_CAP_USER_MEMORY); - if(kvmCapResult == 0){ - return KVMS_MISSING_CAP; - } - - // Set identity map address. - kvmCapResult = ioctl(m_fd, KVM_CHECK_EXTENSION, KVM_CAP_SET_IDENTITY_MAP_ADDR); - if(kvmCapResult == 0) { - return KVMS_MISSING_CAP; - } - - // If we've got this far, we're all good. - return KVMS_SUCCESS; -} - -KvmVMStatus Kvm::CreateVM(KvmVM **vm) { - *vm = new KvmVM(*this); - KvmVMStatus status = (*vm)->Initialize(); - if(status != KVMVMS_SUCCESS) { - delete *vm; - *vm = nullptr; - } else { - m_vms.push_back(*vm); - } - return status; -} - -// -------------------------------------------- -KvmVM::KvmVM(Kvm &kvm) : - m_kvm(kvm) -{ -} - -KvmVM::~KvmVM() { - if(m_fd > 0) { - close(m_fd); - } -} - -KvmVMStatus KvmVM::Initialize() { - // Create the VM - m_fd = ioctl(m_kvm.handle(), KVM_CREATE_VM, 0); - if(m_fd < 0) { - return KVMVMS_CREATE_FAILED; - } - - // Move the identity map. It usually resides at - // 0xfffbc000 which will conflict with the xbox bios. - uint64_t identityMapAddr = 0xD0000000; - if(ioctl(m_fd, KVM_SET_IDENTITY_MAP_ADDR, &identityMapAddr) < 0) { - return KVMVMS_CREATE_FAILED; - } - - return KVMVMS_SUCCESS; -} - -KvmVCPUStatus KvmVM::CreateVCPU(KvmVCPU **vcpu) { - *vcpu = new KvmVCPU(*this, m_vcpus.size()); - KvmVCPUStatus status = (*vcpu)->Initialize(); - - if(status != KVMVCPUS_SUCCESS) { - delete *vcpu; - *vcpu = nullptr; - } else { - m_vcpus.push_back(*vcpu); - } - return status; -} - -KvmVMStatus KvmVM::MapUserMemoryToGuest(void *userMemoryBlock, uint32_t userMemorySize, uint32_t guestBaseAddress) { - - if(((uint64_t)userMemoryBlock) & 0xFFF) { - return KVMVMS_MEM_MISALIGNED; - } - - if(userMemorySize & 0xFFF) { - return KVMVMS_MEMSIZE_MISALIGNED; - } - - KvmMemoryRecord *memoryRecord = (KvmMemoryRecord*)malloc(sizeof(KvmMemoryRecord)); - memset(memoryRecord, 0, sizeof(KvmMemoryRecord)); - memoryRecord->size = userMemorySize; - memoryRecord->startAddr = (uint64_t)userMemoryBlock; - memoryRecord->memoryRegion.memory_size = userMemorySize; - memoryRecord->memoryRegion.userspace_addr = (uint64_t)userMemoryBlock; - memoryRecord->memoryRegion.guest_phys_addr = (uint64_t)guestBaseAddress; - memoryRecord->memoryRegion.slot = (uint32_t)m_memoryRecords.size(); - - m_memoryRecords.push_back(memoryRecord); - - if(ioctl(m_fd, KVM_SET_USER_MEMORY_REGION, &m_memoryRecords[m_memoryRecords.size() - 1]->memoryRegion) < 0) { - return KVMVMS_MEM_ERROR; - } - - return KVMVMS_SUCCESS; -} - -// -------------------------------------------------------------------- -KvmVCPU::KvmVCPU(KvmVM& vm, uint32_t id) : - m_vm(vm), m_vcpuID(id) -{ - -} - -KvmVCPU::~KvmVCPU() { - if(m_fd > 0) { - close(m_fd); - } - - if(m_kvmRun) { - munmap(m_kvmRun, m_kvmRunMmapSize); - } -} - -KvmVCPUStatus KvmVCPU::Initialize() { - - // Create the VCPU. - m_fd = ioctl(m_vm.handle(), KVM_CREATE_VCPU, m_vcpuID); - if(m_fd < 0) { - return KVMVCPUS_CREATE_FAILED; - } - - // Get the kvmRun struct size. - m_kvmRunMmapSize = ioctl(m_vm.kvmHandle(), KVM_GET_VCPU_MMAP_SIZE, 0); - if(m_kvmRunMmapSize < 0) { - return KVMVCPUS_CREATE_FAILED; - } - - m_kvmRun = (struct kvm_run*)mmap(nullptr, (size_t)m_kvmRunMmapSize, - PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, 0); - - if(m_kvmRun < 0) { - return KVMVCPUS_CREATE_FAILED; - } - - return KVMVCPUS_SUCCESS; -} - -KvmVCPUStatus KvmVCPU::Run() { - // Start running! - if(ioctl(m_fd, KVM_RUN, 0) < 0) { - return KVMVCPUS_RUN_FAILED; - } - - return KVMVCPUS_SUCCESS; -} - -KvmVCPUStatus KvmVCPU::Interrupt(uint8_t vector) { - struct kvm_interrupt kvmInterrupt; - - kvmInterrupt.irq = (uint32_t)vector; - - if(ioctl(m_fd, KVM_INTERRUPT, &kvmInterrupt) < 0) { - return KVMVCPUS_INTERRUPT_FAILED; - } - - return KVMVCPUS_SUCCESS; -} - -KvmVCPUStatus KvmVCPU::GetRegisters(struct kvm_regs *regs) { - if(ioctl(m_fd, KVM_GET_REGS, regs) < 0) { - return KVMVCPUS_REG_ERROR; - } - return KVMVCPUS_SUCCESS; -} - -KvmVCPUStatus KvmVCPU::SetRegisters(struct kvm_regs regs) { - if(ioctl(m_fd, KVM_SET_REGS, ®s) < 0) { - return KVMVCPUS_REG_ERROR; - } - return KVMVCPUS_SUCCESS; -} - -KvmVCPUStatus KvmVCPU::GetSRegisters(struct kvm_sregs *sregs) { - if(ioctl(m_fd, KVM_GET_SREGS, sregs) < 0) { - return KVMVCPUS_REG_ERROR; - } - return KVMVCPUS_SUCCESS; -} - -KvmVCPUStatus KvmVCPU::SetSRegisters(struct kvm_sregs sregs) { - if(ioctl(m_fd, KVM_SET_SREGS, &sregs) < 0) { - return KVMVCPUS_REG_ERROR; - } - return KVMVCPUS_SUCCESS; -} - -KvmVCPUStatus KvmVCPU::GetFPURegisters(struct kvm_fpu *fpuRegs) { - if(ioctl(m_fd, KVM_GET_FPU, fpuRegs) < 0) { - return KVMVCPUS_REG_ERROR; - } - return KVMVCPUS_SUCCESS; -} - -KvmVCPUStatus KvmVCPU::SetFPURegisters(struct kvm_fpu fpuRegs) { - if(ioctl(m_fd, KVM_SET_FPU, &fpuRegs) < 0) { - return KVMVCPUS_REG_ERROR; - } - return KVMVCPUS_SUCCESS; -} - -KvmVCPUStatus KvmVCPU::GetMSRs(struct kvm_msrs *msrs) { - if(ioctl(m_fd, KVM_GET_MSRS, msrs) < 0) { - return KVMVCPUS_REG_ERROR; - } - return KVMVCPUS_SUCCESS; -} - -KvmVCPUStatus KvmVCPU::SetMSRs(struct kvm_msrs msrs) { - if(ioctl(m_fd, KVM_GET_FPU, &msrs) < 0) { - return KVMVCPUS_REG_ERROR; - } - return KVMVCPUS_SUCCESS; -} diff --git a/src/cpu-module-kvm/kvm/kvm.h b/src/cpu-module-kvm/kvm/kvm.h deleted file mode 100644 index ee4c3bd..0000000 --- a/src/cpu-module-kvm/kvm/kvm.h +++ /dev/null @@ -1,107 +0,0 @@ -#pragma once - -#include -#include -#include - -enum KvmStatus { - KVMS_OPEN_FAILED, - KVMS_SUCCESS, - KVMS_API_VERSION_UNSUPPORTED, - KVMS_MISSING_CAP -}; - -enum KvmVMStatus { - KVMVMS_CREATE_FAILED, - KVMVMS_SUCCESS, - KVMVMS_MEM_MISALIGNED, - KVMVMS_MEMSIZE_MISALIGNED, - KVMVMS_MEM_ERROR -}; - -enum KvmVCPUStatus { - KVMVCPUS_CREATE_FAILED, - KVMVCPUS_SUCCESS, - KVMVCPUS_RUN_FAILED, - KVMVCPUS_REG_ERROR, - KVMVCPUS_INTERRUPT_FAILED -}; - -typedef struct { - uint32_t size; - uint64_t startAddr; - struct kvm_userspace_memory_region memoryRegion; -} KvmMemoryRecord; - -class KvmVM; -class KvmVCPU; - -class Kvm { -public: - Kvm(); - ~Kvm(); - - KvmStatus Initialize(); - KvmVMStatus CreateVM(KvmVM **vm); - const int handle() const { return m_fd; } - -private: - int m_fd; - std::vector m_vms; -}; - -class KvmVM { -public: - KvmVMStatus MapUserMemoryToGuest(void *userMemoryBlock, uint32_t userMemorySize, uint32_t guestBaseAddress); - KvmVCPUStatus CreateVCPU(KvmVCPU **vcpu); - - const int handle() const { return m_fd; } - const int kvmHandle() const { return m_kvm.handle(); } - -private: - KvmVM(Kvm &kvm); - ~KvmVM(); - - KvmVMStatus Initialize(); - - int m_fd; - std::vector m_vcpus; - std::vector m_memoryRecords; - - Kvm& m_kvm; - - friend class Kvm; -}; - -class KvmVCPU { -public: - KvmVCPUStatus Run(); - KvmVCPUStatus Interrupt(uint8_t vector); - - KvmVCPUStatus GetRegisters(struct kvm_regs* regs); - KvmVCPUStatus SetRegisters(struct kvm_regs regs); - KvmVCPUStatus GetSRegisters(struct kvm_sregs* sregs); - KvmVCPUStatus SetSRegisters(struct kvm_sregs sregs); - KvmVCPUStatus GetFPURegisters(struct kvm_fpu *fpuRegs); - KvmVCPUStatus SetFPURegisters(struct kvm_fpu fpuRegs); - KvmVCPUStatus GetMSRs(struct kvm_msrs* msrs); - KvmVCPUStatus SetMSRs(struct kvm_msrs msrs); - - struct kvm_run* kvmRun() { return m_kvmRun; } - -private: - KvmVCPU(KvmVM &vm, uint32_t id); - ~KvmVCPU(); - - KvmVCPUStatus Initialize(); - - KvmVM& m_vm; - - uint32_t m_vcpuID; - int m_fd; - - struct kvm_run* m_kvmRun; - int m_kvmRunMmapSize; - - friend class KvmVM; -}; \ No newline at end of file diff --git a/src/cpu-module-whvp/CMakeLists.txt b/src/cpu-module-whvp/CMakeLists.txt deleted file mode 100644 index e0e1109..0000000 --- a/src/cpu-module-whvp/CMakeLists.txt +++ /dev/null @@ -1,48 +0,0 @@ -# Add sources -file(GLOB DIR_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/whvp/*.h - ) - -file(GLOB DIR_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/whvp/*.cpp - ) - -set(SOURCES ${SOURCES} - ${DIR_HEADERS} - ${DIR_SOURCES} - ) - - -# Export module -add_definitions(-DMODULE_EXPORTS) - -# Add Visual Studio filters to better organize the code -vs_set_filters("${SOURCES}") - -# Main Executable -if(NOT MSVC) - add_definitions("-Wall -Werror -O0 -g") -endif() -add_library(cpu-module-whvp SHARED "${SOURCES}") -target_include_directories(cpu-module-whvp PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - -# Include common module code -target_link_libraries(cpu-module-whvp common cpu-module) - -# Make the Debug and RelWithDebInfo targets use Program Database for Edit and Continue for easier debugging -vs_use_edit_and_continue() - -# Copy DLL to CLI output directory -string(TOLOWER ${CPU_MODULE} CPU_MODULE_LC) -if(CPU_MODULE_LC STREQUAL whvp) - if(MSVC) - add_custom_command(TARGET cpu-module-whvp - POST_BUILD - COMMAND if not exist \"$(ProjectDir)..\\cli\\$(Configuration)\\modules\" mkdir \"$(ProjectDir)..\\cli\\$(Configuration)\\modules\" - COMMAND copy /b /y \"$(TargetDir)*.dll\" \"$(ProjectDir)..\\cli\\$(Configuration)\\modules\" - COMMENT "Copy DLLs to target directory") - endif() -endif() - diff --git a/src/cpu-module-whvp/cpu_whvp.cpp b/src/cpu-module-whvp/cpu_whvp.cpp deleted file mode 100644 index 13266dc..0000000 --- a/src/cpu-module-whvp/cpu_whvp.cpp +++ /dev/null @@ -1,479 +0,0 @@ -#include -#include "cpu_whvp.h" - -#include "vixen/log.h" - -namespace vixen { -namespace cpu { - -WhvpCpu::WhvpCpu() { - m_whvp = nullptr; - m_partition = nullptr; - m_vcpu = nullptr; -} - -WhvpCpu::~WhvpCpu() { - if (m_whvp != nullptr) { - // Deleting this object will automatically delete the partition and VCPU - delete m_whvp; - m_whvp = nullptr; - } -} - -CPUInitStatus WhvpCpu::InitializeImpl() { - if (m_whvp == nullptr) { - m_whvp = new WinHvPlatform(); - - if (!m_whvp->IsPresent()) { - return CPUS_INIT_PLATFORM_INIT_FAILED; - } - - auto partStatus = m_whvp->CreatePartition(&m_partition); - if (partStatus != WHVPS_SUCCESS) { - delete m_whvp; - m_whvp = nullptr; - return CPUS_INIT_CREATE_VM_FAILED; - } - - // Give one processor to the partition - WHV_PARTITION_PROPERTY partitionProperty; - partitionProperty.ProcessorCount = 1; - partStatus = m_partition->SetProperty(WHvPartitionPropertyCodeProcessorCount, &partitionProperty); - if (WHVPS_SUCCESS != partStatus) { - return CPUS_INIT_CREATE_VM_FAILED; - } - - // Setup the partition - partStatus = m_partition->Setup(); - if (WHVPS_SUCCESS != partStatus) { - return CPUS_INIT_CREATE_VM_FAILED; - } - - auto vcpuStatus = m_partition->CreateVCPU(&m_vcpu, 0); - if (vcpuStatus != WHVVCPUS_SUCCESS) { - delete m_whvp; - m_whvp = nullptr; - return CPUS_INIT_CREATE_CPU_FAILED; - } - - m_vcpu->SetIoPortCallback(IoPortCallback); - m_vcpu->SetMemoryCallback(MemoryCallback); - } - - return CPUS_INIT_OK; -} - -CPUStatus WhvpCpu::RunImpl() { - // Run CPU - auto status = m_vcpu->Run(); - - // Check VM exit status - if (status != WHVVCPUS_SUCCESS) { - return CPUS_FAILED; - } - - // Handle exit status using tunnel - switch (m_vcpu->ExitContext()->ExitReason) { - case WHvRunVpExitReasonX64Halt: m_exitInfo.reason = CPU_EXIT_HLT; break; // HLT instruction - case WHvRunVpExitReasonX64IoPortAccess: m_exitInfo.reason = CPU_EXIT_NORMAL; break; // I/O (in / out instructions) - case WHvRunVpExitReasonMemoryAccess: m_exitInfo.reason = CPU_EXIT_NORMAL; break; // MMIO - case WHvRunVpExitReasonX64InterruptWindow: m_exitInfo.reason = CPU_EXIT_NORMAL; break; // Interrupt window (never requested, should never happen) - case WHvRunVpExitReasonCanceled: m_exitInfo.reason = CPU_EXIT_NORMAL; break; // Execution cancelled - case WHvRunVpExitReasonNone: m_exitInfo.reason = CPU_EXIT_NORMAL; break; // VM exited for no reason - case WHvRunVpExitReasonException: m_exitInfo.reason = CPU_EXIT_ERROR; break; // VCPU threw an unhandled exception (the kernel should handle them) - case WHvRunVpExitReasonX64Cpuid: m_exitInfo.reason = CPU_EXIT_ERROR; break; // CPUID instruction (not enabled, should never happen) - case WHvRunVpExitReasonX64MsrAccess: m_exitInfo.reason = CPU_EXIT_ERROR; break; // MSR access (not enabled, should never happen) - case WHvRunVpExitReasonUnsupportedFeature: m_exitInfo.reason = CPU_EXIT_ERROR; break; // Host CPU does not support a feature needed by the VM - case WHvRunVpExitReasonInvalidVpRegisterValue: m_exitInfo.reason = CPU_EXIT_ERROR; break; // VCPU has an invalid register - case WHvRunVpExitReasonUnrecoverableException: m_exitInfo.reason = CPU_EXIT_ERROR; break; // Unrecoverable exception - } - - return CPUS_OK; -} - -InterruptResult WhvpCpu::InterruptImpl(uint8_t vector) { - // Cancel execution of the VCPU to give the emulator a chance to inject the interrupt request - m_vcpu->CancelRun(); - - return INTR_SUCCESS; -} - -CPUMemMapStatus WhvpCpu::MemMapSubregion(MemoryRegion *subregion) { - switch (subregion->m_type) { - case MEM_REGION_MMIO: - { - // All unmapped regions in a Windows Hypervisor Platform VM are MMIO, no need to allocate - return CPUS_MMAP_OK; - } - case MEM_REGION_NONE: - { - // This should not happen - assert(0); - return CPUS_MMAP_INVALID_TYPE; - } - case MEM_REGION_RAM: - case MEM_REGION_ROM: - { - // Region is either RAM or ROM, map it accordingly - WHV_MAP_GPA_RANGE_FLAGS flags = WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagExecute | ((subregion->m_type == MEM_REGION_RAM) ? WHvMapGpaRangeFlagWrite : WHvMapGpaRangeFlagNone); - auto status = m_partition->MapGpaRange(subregion->m_data, subregion->m_start, subregion->m_size, flags); - switch (status) { - case WHVPS_SUCCESS: return CPUS_MMAP_OK; - case WHVPS_UNINITIALIZED: return CPUS_MMAP_CPU_UNINITIALIZED; - case WHVPS_FAILED: return CPUS_MMAP_MAPPING_FAILED; - default: return CPUS_MMAP_UNHANDLED_ERROR; - } - } - default: - // This should not happen - assert(0); - return CPUS_MMAP_INVALID_TYPE; - } -} - -CPUOperationStatus WhvpCpu::RegRead(enum CpuReg reg, uint32_t *value) { - WHV_REGISTER_NAME regs[1]; - WHV_REGISTER_VALUE vals[1]; - - switch (reg) { - case REG_EIP: regs[0] = WHvX64RegisterRip; break; - case REG_EFLAGS: regs[0] = WHvX64RegisterRflags; break; - case REG_EAX: regs[0] = WHvX64RegisterRax; break; - case REG_ECX: regs[0] = WHvX64RegisterRcx; break; - case REG_EDX: regs[0] = WHvX64RegisterRdx; break; - case REG_EBX: regs[0] = WHvX64RegisterRbx; break; - case REG_ESI: regs[0] = WHvX64RegisterRsi; break; - case REG_EDI: regs[0] = WHvX64RegisterRdi; break; - case REG_ESP: regs[0] = WHvX64RegisterRsp; break; - case REG_EBP: regs[0] = WHvX64RegisterRbp; break; - case REG_CS: regs[0] = WHvX64RegisterCs; break; - case REG_SS: regs[0] = WHvX64RegisterSs; break; - case REG_DS: regs[0] = WHvX64RegisterDs; break; - case REG_ES: regs[0] = WHvX64RegisterEs; break; - case REG_FS: regs[0] = WHvX64RegisterFs; break; - case REG_GS: regs[0] = WHvX64RegisterGs; break; - case REG_TR: regs[0] = WHvX64RegisterTr; break; - case REG_CR0: regs[0] = WHvX64RegisterCr0; break; - case REG_CR2: regs[0] = WHvX64RegisterCr2; break; - case REG_CR3: regs[0] = WHvX64RegisterCr3; break; - case REG_CR4: regs[0] = WHvX64RegisterCr4; break; - default: return CPUS_OP_INVALID_REGISTER; - } - - auto status = m_vcpu->GetRegisters(regs, 1, vals); - if (status != WHVVCPUS_SUCCESS) { - return CPUS_OP_FAILED; - } - - switch (reg) { - case REG_EIP: case REG_EFLAGS: case REG_EAX: case REG_ECX: case REG_EDX: case REG_EBX: - case REG_ESI: case REG_EDI: case REG_ESP: case REG_EBP: case REG_CR0: case REG_CR2: case REG_CR3: case REG_CR4: - *value = vals[0].Reg32; - break; - case REG_CS: case REG_SS: case REG_DS: case REG_ES: case REG_FS: case REG_GS: case REG_TR: - *value = vals[0].Segment.Selector; - break; - default: - return CPUS_OP_INVALID_REGISTER; - } - - return CPUS_OP_OK; -} - -CPUOperationStatus WhvpCpu::RegWrite(enum CpuReg reg, uint32_t value) { - WHV_REGISTER_NAME regs[1]; - WHV_REGISTER_VALUE vals[1]; - - switch (reg) { - case REG_EIP: regs[0] = WHvX64RegisterRip; break; - case REG_EFLAGS: regs[0] = WHvX64RegisterRflags; break; - case REG_EAX: regs[0] = WHvX64RegisterRax; break; - case REG_ECX: regs[0] = WHvX64RegisterRcx; break; - case REG_EDX: regs[0] = WHvX64RegisterRdx; break; - case REG_EBX: regs[0] = WHvX64RegisterRbx; break; - case REG_ESI: regs[0] = WHvX64RegisterRsi; break; - case REG_EDI: regs[0] = WHvX64RegisterRdi; break; - case REG_ESP: regs[0] = WHvX64RegisterRsp; break; - case REG_EBP: regs[0] = WHvX64RegisterRbp; break; - case REG_CS: regs[0] = WHvX64RegisterCs; break; - case REG_SS: regs[0] = WHvX64RegisterSs; break; - case REG_DS: regs[0] = WHvX64RegisterDs; break; - case REG_ES: regs[0] = WHvX64RegisterEs; break; - case REG_FS: regs[0] = WHvX64RegisterFs; break; - case REG_GS: regs[0] = WHvX64RegisterGs; break; - case REG_TR: regs[0] = WHvX64RegisterTr; break; - case REG_CR0: regs[0] = WHvX64RegisterCr0; break; - case REG_CR2: regs[0] = WHvX64RegisterCr2; break; - case REG_CR3: regs[0] = WHvX64RegisterCr3; break; - case REG_CR4: regs[0] = WHvX64RegisterCr4; break; - default: return CPUS_OP_INVALID_REGISTER; - } - - switch (reg) { - case REG_EAX: case REG_ECX: case REG_EDX: case REG_EBX: - case REG_ESI: case REG_EDI: case REG_ESP: case REG_EBP: - case REG_CR0: case REG_CR2: case REG_CR3: case REG_CR4: - case REG_EIP: - vals[0].Reg32 = value; - break; - case REG_EFLAGS: - vals[0].Reg32 = (value | 0x2) & ~0x8028; - break; - case REG_CS: case REG_SS: case REG_DS: case REG_ES: case REG_FS: case REG_GS: case REG_TR: - { - vals[0].Segment.Selector = value; - - // Get GDT entry from memory - uint32_t gdtAddr; - uint32_t gdtSize; - GetGDT(&gdtAddr, &gdtSize); - - GDTEntry gdtEntry; - VMemRead(gdtAddr + value, sizeof(GDTEntry), &gdtEntry); - - // Fill in the rest of the CS info with data from the GDT entry - vals[0].Segment.Attributes = gdtEntry.data.access | (gdtEntry.data.flags << 12); - vals[0].Segment.Base = gdtEntry.GetBase(); - vals[0].Segment.Limit = gdtEntry.GetLimit(); - break; - } - default: - return CPUS_OP_INVALID_REGISTER; - } - - auto status = m_vcpu->SetRegisters(regs, 1, vals); - if (status != WHVVCPUS_SUCCESS) { - return CPUS_OP_FAILED; - } - - return CPUS_OP_OK; -} - -CPUOperationStatus WhvpCpu::RegRead(CpuReg regs[], uint32_t values[], uint8_t numRegs) { - WHV_REGISTER_NAME *whvpRegs = new WHV_REGISTER_NAME[numRegs]; - WHV_REGISTER_VALUE *whvpVals = new WHV_REGISTER_VALUE[numRegs]; - - for (uint8_t i = 0; i < numRegs; i++) { - switch (regs[i]) { - case REG_EIP: whvpRegs[i] = WHvX64RegisterRip; break; - case REG_EFLAGS: whvpRegs[i] = WHvX64RegisterRflags; break; - case REG_EAX: whvpRegs[i] = WHvX64RegisterRax; break; - case REG_ECX: whvpRegs[i] = WHvX64RegisterRcx; break; - case REG_EDX: whvpRegs[i] = WHvX64RegisterRdx; break; - case REG_EBX: whvpRegs[i] = WHvX64RegisterRbx; break; - case REG_ESI: whvpRegs[i] = WHvX64RegisterRsi; break; - case REG_EDI: whvpRegs[i] = WHvX64RegisterRdi; break; - case REG_ESP: whvpRegs[i] = WHvX64RegisterRsp; break; - case REG_EBP: whvpRegs[i] = WHvX64RegisterRbp; break; - case REG_CS: whvpRegs[i] = WHvX64RegisterCs; break; - case REG_SS: whvpRegs[i] = WHvX64RegisterSs; break; - case REG_DS: whvpRegs[i] = WHvX64RegisterDs; break; - case REG_ES: whvpRegs[i] = WHvX64RegisterEs; break; - case REG_FS: whvpRegs[i] = WHvX64RegisterFs; break; - case REG_GS: whvpRegs[i] = WHvX64RegisterGs; break; - case REG_TR: whvpRegs[i] = WHvX64RegisterTr; break; - case REG_CR0: whvpRegs[i] = WHvX64RegisterCr0; break; - case REG_CR2: whvpRegs[i] = WHvX64RegisterCr2; break; - case REG_CR3: whvpRegs[i] = WHvX64RegisterCr3; break; - case REG_CR4: whvpRegs[i] = WHvX64RegisterCr4; break; - default: delete[] whvpRegs; delete[] whvpVals; return CPUS_OP_INVALID_REGISTER; - } - } - - auto status = m_vcpu->GetRegisters(whvpRegs, numRegs, whvpVals); - if (status != WHVVCPUS_SUCCESS) { - delete[] whvpRegs; - delete[] whvpVals; - return CPUS_OP_FAILED; - } - - for (uint8_t i = 0; i < numRegs; i++) { - switch (regs[i]) { - case REG_EIP: case REG_EFLAGS: case REG_EAX: case REG_ECX: case REG_EDX: case REG_EBX: - case REG_ESI: case REG_EDI: case REG_ESP: case REG_EBP: case REG_CR0: case REG_CR2: case REG_CR3: case REG_CR4: - values[i] = whvpVals[i].Reg32; - break; - case REG_CS: case REG_SS: case REG_DS: case REG_ES: case REG_FS: case REG_GS: case REG_TR: - values[i] = whvpVals[i].Segment.Selector; - break; - default: - delete[] whvpRegs; - delete[] whvpVals; - return CPUS_OP_INVALID_REGISTER; - } - } - - delete[] whvpRegs; - delete[] whvpVals; - return CPUS_OP_OK; -} - -CPUOperationStatus WhvpCpu::RegWrite(CpuReg regs[], uint32_t values[], uint8_t numRegs) { - WHV_REGISTER_NAME *whvpRegs = new WHV_REGISTER_NAME[numRegs]; - WHV_REGISTER_VALUE *whvpVals = new WHV_REGISTER_VALUE[numRegs]; - - for (uint8_t i = 0; i < numRegs; i++) { - switch (regs[i]) { - case REG_EIP: whvpRegs[i] = WHvX64RegisterRip; break; - case REG_EFLAGS: whvpRegs[i] = WHvX64RegisterRflags; break; - case REG_EAX: whvpRegs[i] = WHvX64RegisterRax; break; - case REG_ECX: whvpRegs[i] = WHvX64RegisterRcx; break; - case REG_EDX: whvpRegs[i] = WHvX64RegisterRdx; break; - case REG_EBX: whvpRegs[i] = WHvX64RegisterRbx; break; - case REG_ESI: whvpRegs[i] = WHvX64RegisterRsi; break; - case REG_EDI: whvpRegs[i] = WHvX64RegisterRdi; break; - case REG_ESP: whvpRegs[i] = WHvX64RegisterRsp; break; - case REG_EBP: whvpRegs[i] = WHvX64RegisterRbp; break; - case REG_CS: whvpRegs[i] = WHvX64RegisterCs; break; - case REG_SS: whvpRegs[i] = WHvX64RegisterSs; break; - case REG_DS: whvpRegs[i] = WHvX64RegisterDs; break; - case REG_ES: whvpRegs[i] = WHvX64RegisterEs; break; - case REG_FS: whvpRegs[i] = WHvX64RegisterFs; break; - case REG_GS: whvpRegs[i] = WHvX64RegisterGs; break; - case REG_TR: whvpRegs[i] = WHvX64RegisterTr; break; - case REG_CR0: whvpRegs[i] = WHvX64RegisterCr0; break; - case REG_CR2: whvpRegs[i] = WHvX64RegisterCr2; break; - case REG_CR3: whvpRegs[i] = WHvX64RegisterCr3; break; - case REG_CR4: whvpRegs[i] = WHvX64RegisterCr4; break; - default: delete[] whvpRegs; delete[] whvpVals; return CPUS_OP_INVALID_REGISTER; - } - - switch (regs[i]) { - case REG_EAX: case REG_ECX: case REG_EDX: case REG_EBX: - case REG_ESI: case REG_EDI: case REG_ESP: case REG_EBP: - case REG_CR0: case REG_CR2: case REG_CR3: case REG_CR4: - case REG_EIP: - whvpVals[i].Reg32 = values[i]; - break; - case REG_EFLAGS: - whvpVals[i].Reg32 = (values[i] | 0x2) & ~0x8028; - break; - case REG_CS: case REG_SS: case REG_DS: case REG_ES: case REG_FS: case REG_GS: case REG_TR: - { - whvpVals[i].Segment.Selector = values[i]; - - // Get GDT entry from memory - uint32_t gdtAddr; - uint32_t gdtSize; - GetGDT(&gdtAddr, &gdtSize); - - GDTEntry gdtEntry; - VMemRead(gdtAddr + values[i], sizeof(GDTEntry), &gdtEntry); - - // Fill in the rest of the CS info with data from the GDT entry - whvpVals[i].Segment.Attributes = gdtEntry.data.access | (gdtEntry.data.flags << 12); - whvpVals[i].Segment.Base = gdtEntry.GetBase(); - whvpVals[i].Segment.Limit = gdtEntry.GetLimit(); - break; - } - default: - delete[] whvpRegs; - delete[] whvpVals; - return CPUS_OP_INVALID_REGISTER; - } - } - - auto status = m_vcpu->SetRegisters(whvpRegs, numRegs, whvpVals); - if (status != WHVVCPUS_SUCCESS) { - return CPUS_OP_FAILED; - } - - return CPUS_OP_OK; -} - -CPUOperationStatus WhvpCpu::GetGDT(uint32_t *addr, uint32_t *size) { - WHV_REGISTER_NAME reg[1] = { WHvX64RegisterGdtr }; - WHV_REGISTER_VALUE val[1]; - auto status = m_vcpu->GetRegisters(reg, 1, val); - if (status != WHVVCPUS_SUCCESS) { - return CPUS_OP_FAILED; - } - *addr = val[0].Table.Base; - *size = val[0].Table.Limit; - - return CPUS_OP_OK; -} - -CPUOperationStatus WhvpCpu::SetGDT(uint32_t addr, uint32_t size) { - WHV_REGISTER_NAME reg[1] = { WHvX64RegisterGdtr }; - WHV_REGISTER_VALUE val[1]; - val[0].Table.Base = addr; - val[0].Table.Limit = size; - - auto status = m_vcpu->SetRegisters(reg, 1, val); - if (status != WHVVCPUS_SUCCESS) { - return CPUS_OP_FAILED; - } - - return CPUS_OP_OK; -} - -CPUOperationStatus WhvpCpu::GetIDT(uint32_t *addr, uint32_t *size) { - WHV_REGISTER_NAME reg[1] = { WHvX64RegisterIdtr }; - WHV_REGISTER_VALUE val[1]; - auto status = m_vcpu->GetRegisters(reg, 1, val); - if (status != WHVVCPUS_SUCCESS) { - return CPUS_OP_FAILED; - } - *addr = val[0].Table.Base; - *size = val[0].Table.Limit; - - return CPUS_OP_OK; -} - -CPUOperationStatus WhvpCpu::SetIDT(uint32_t addr, uint32_t size) { - WHV_REGISTER_NAME reg[1] = { WHvX64RegisterIdtr }; - WHV_REGISTER_VALUE val[1]; - val[0].Table.Base = addr; - val[0].Table.Limit = size; - - auto status = m_vcpu->SetRegisters(reg, 1, val); - if (status != WHVVCPUS_SUCCESS) { - return CPUS_OP_FAILED; - } - - return CPUS_OP_OK; -} - -CPUOperationStatus WhvpCpu::InjectInterrupt(uint8_t vector) { - auto status = m_vcpu->Interrupt(vector); - if (status != WHVVCPUS_SUCCESS) { - return CPUS_OP_FAILED; - } - - return CPUS_OP_OK; -} - -bool WhvpCpu::CanInjectInterrupt() { - // TODO: should probably take a look at m_vcpu->ExitContext()->InterruptWindow - return true; -} - -void WhvpCpu::RequestInterruptWindow() { - // TODO: should probably take a look at m_vcpu->ExitContext()->InterruptWindow -} - -HRESULT WhvpCpu::IoPortCallback(PVOID context, WHV_EMULATOR_IO_ACCESS_INFO *io) { - WhvpCpu *cpu = (WhvpCpu *)context; - if (io->Direction == WHV_IO_OUT) { - cpu->m_ioMapper->IOWrite(io->Port, io->Data, io->AccessSize); - } - else { - cpu->m_ioMapper->IORead(io->Port, &io->Data, io->AccessSize); - } - return S_OK; -} - -HRESULT WhvpCpu::MemoryCallback(PVOID context, WHV_EMULATOR_MEMORY_ACCESS_INFO *mem) { - WhvpCpu *cpu = (WhvpCpu *)context; - if (mem->Direction == WHV_IO_OUT) { - cpu->m_ioMapper->MMIOWrite(mem->GpaAddress, *(uint32_t *)mem->Data, mem->AccessSize); - } - else { - cpu->m_ioMapper->MMIORead(mem->GpaAddress, (uint32_t *)mem->Data, mem->AccessSize); - } - return S_OK; -} - -} -} diff --git a/src/cpu-module-whvp/cpu_whvp.h b/src/cpu-module-whvp/cpu_whvp.h deleted file mode 100644 index 906b3b9..0000000 --- a/src/cpu-module-whvp/cpu_whvp.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include "whvp/whvp.h" -#include "vixen/cpu.h" - -namespace vixen { -namespace cpu { - -/*! - * Windows Hypervisor Platform CPU implementation. - * - * This is the implementation of the CPU interface using - * [Windows Hypervisor Platform](https://docs.microsoft.com/en-us/virtualization/api/). - */ -class WhvpCpu : public Cpu { -public: - WhvpCpu(); - ~WhvpCpu(); - - CPUInitStatus InitializeImpl(); - - CPUStatus RunImpl(); - InterruptResult InterruptImpl(uint8_t vector); - - CPUMemMapStatus MemMapSubregion(MemoryRegion *subregion); - - CPUOperationStatus RegRead(enum CpuReg reg, uint32_t *value); - CPUOperationStatus RegWrite(enum CpuReg reg, uint32_t value); - - CPUOperationStatus RegRead(enum CpuReg regs[], uint32_t values[], uint8_t numRegs) override; - CPUOperationStatus RegWrite(enum CpuReg regs[], uint32_t values[], uint8_t numRegs) override; - - CPUOperationStatus GetGDT(uint32_t *addr, uint32_t *size); - CPUOperationStatus SetGDT(uint32_t addr, uint32_t size); - - CPUOperationStatus GetIDT(uint32_t *addr, uint32_t *size); - CPUOperationStatus SetIDT(uint32_t addr, uint32_t size); - -protected: - CPUOperationStatus InjectInterrupt(uint8_t vector); - bool CanInjectInterrupt(); - void RequestInterruptWindow(); - -private: - WinHvPlatform *m_whvp; - WHvPartition *m_partition; - WHvVCPU *m_vcpu; - - static HRESULT IoPortCallback(PVOID context, WHV_EMULATOR_IO_ACCESS_INFO *io); - static HRESULT MemoryCallback(PVOID context, WHV_EMULATOR_MEMORY_ACCESS_INFO *mem); -}; - -} -} diff --git a/src/cpu-module-whvp/cpu_whvp_module.cpp b/src/cpu-module-whvp/cpu_whvp_module.cpp deleted file mode 100644 index 2808af0..0000000 --- a/src/cpu-module-whvp/cpu_whvp_module.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include - -#include "vixen/cpu_module_decl.h" -#include "cpu_whvp_module.h" -#include "cpu_whvp.h" - -namespace vixen { -namespace modules { -namespace cpu { - -CPU_MODULE_BEGIN -CPU_MODULE_INFO(WhvpCPUModule, "Windows Hypervisor Platform CPU Module", "0.0.1") -CPU_MODULE_END - -Cpu *WhvpCPUModule::GetCPU() { - return &m_cpu; -} - -void WhvpCPUModule::FreeCPU(Cpu *cpu) { -} - -void WhvpCPUModule::Cleanup() { -} - -} -} -} diff --git a/src/cpu-module-whvp/cpu_whvp_module.h b/src/cpu-module-whvp/cpu_whvp_module.h deleted file mode 100644 index e98c61e..0000000 --- a/src/cpu-module-whvp/cpu_whvp_module.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "vixen/cpu.h" -#include "cpu_whvp.h" - -namespace vixen { -namespace modules { -namespace cpu { - -class WhvpCPUModule : public ICPUModule { -public: - Cpu *GetCPU(); - void FreeCPU(Cpu *cpu); - void Cleanup(); -private: - WhvpCpu m_cpu; -}; - -} -} -} diff --git a/src/cpu-module-whvp/whvp/whvp.cpp b/src/cpu-module-whvp/whvp/whvp.cpp deleted file mode 100644 index 38746c3..0000000 --- a/src/cpu-module-whvp/whvp/whvp.cpp +++ /dev/null @@ -1,468 +0,0 @@ -#include "whvp.h" - -#pragma comment(lib, "WinHvPlatform.lib") -#pragma comment(lib, "WinHvEmulation.lib") - -WinHvPlatform::WinHvPlatform() { - WHV_CAPABILITY cap; - - // Check for presence of the hypervisor platform - WHvStatus status = GetCapability(WHvCapabilityCodeHypervisorPresent, &cap); - if (WHVS_SUCCESS != status) { - m_present = false; - return; - } - - m_present = cap.HypervisorPresent; -} - -WinHvPlatform::~WinHvPlatform() { - // Delete all partitions created with this object - for (auto it = m_partitions.begin(); it != m_partitions.end(); it++) { - delete (*it); - } - m_partitions.clear(); -} - -WHvStatus WinHvPlatform::GetCapability(WHV_CAPABILITY_CODE code, WHV_CAPABILITY *pCap) { - UINT32 size; - HRESULT hr = WHvGetCapability(code, pCap, sizeof(WHV_CAPABILITY), &size); - if (S_OK != hr) { - switch (hr) { - case WHV_E_UNKNOWN_CAPABILITY: - return WHVS_INVALID_CAPABILITY; - default: - return WHVS_FAILED; - } - } - return WHVS_SUCCESS; -} - -WHvPartitionStatus WinHvPlatform::CreatePartition(WHvPartition **ppPartition) { - // Create and initialize the partition - WHvPartition *partition = new WHvPartition(this); - WHvPartitionStatus status = partition->Initialize(); - if (status != WHVPS_SUCCESS) { - delete partition; - return status; - } - - // Add it to the vector so that we can clean up later - m_partitions.push_back(partition); - *ppPartition = partition; - - return WHVPS_SUCCESS; -} - -WHvPartitionStatus WinHvPlatform::DeletePartition(WHvPartition **ppPartition) { - // Null check the pointers - if (ppPartition == nullptr) { - return WHVPS_INVALID_POINTER; - } - if (*ppPartition == nullptr) { - return WHVPS_INVALID_POINTER; - } - - // Make sure the partition was created by this platform object - if ((*ppPartition)->m_platform != this) { - return WHVPS_INVALID_OWNER; - } - - // Try to close the partition - WHvPartitionStatus closeStatus = (*ppPartition)->Close(); - if (closeStatus != WHVPS_SUCCESS) { - return closeStatus; - } - - // Remove it from the clean up vector - for (auto it = m_partitions.begin(); it != m_partitions.end(); it++) { - if (*it == *ppPartition) { - m_partitions.erase(it); - break; - } - } - - // Delete and clear the pointer - delete *ppPartition; - *ppPartition = nullptr; - - return WHVPS_SUCCESS; -} - - -WHvPartition::WHvPartition(WinHvPlatform *platform) - : m_platform(platform) - , m_handle(INVALID_HANDLE_VALUE) -{ -} - -WHvPartition::~WHvPartition() { - // Delete all VCPUs created with this partition - for (auto it = m_vcpus.begin(); it != m_vcpus.end(); it++) { - delete (*it); - } - m_vcpus.clear(); - - // Release resources bound to this partition - Close(); -} - -WHvPartitionStatus WHvPartition::Close() { - // Check if the handle is valid - if (m_handle == INVALID_HANDLE_VALUE) { - return WHVPS_ALREADY_DELETED; - } - - // Delete the partition - HRESULT hr = WHvDeletePartition(m_handle); - if (S_OK != hr) { - return WHVPS_DELETE_FAILED; - } - - // Clear the handle - m_handle = INVALID_HANDLE_VALUE; - - return WHVPS_SUCCESS; -} - -WHvPartitionStatus WHvPartition::Initialize() { - // Check if the handle is valid - if (m_handle != INVALID_HANDLE_VALUE) { - return WHVPS_ALREADY_CREATED; - } - - // Create the partition - HRESULT hr = WHvCreatePartition(&m_handle); - if (S_OK != hr) { - m_handle = INVALID_HANDLE_VALUE; - return WHVPS_CREATE_FAILED; - } - - return WHVPS_SUCCESS; -} - -WHvPartitionStatus WHvPartition::GetProperty(WHV_PARTITION_PROPERTY_CODE code, WHV_PARTITION_PROPERTY *ppProperty) { - // Check if the handle is valid - if (m_handle == INVALID_HANDLE_VALUE) { - return WHVPS_UNINITIALIZED; - } - - // Get the specified partition property - UINT32 size; - HRESULT hr = WHvGetPartitionProperty(m_handle, code, ppProperty, sizeof(WHV_PARTITION_PROPERTY), &size); - if (S_OK != hr) { - return WHVPS_FAILED; - } - return WHVPS_SUCCESS; -} - -WHvPartitionStatus WHvPartition::SetProperty(WHV_PARTITION_PROPERTY_CODE code, WHV_PARTITION_PROPERTY *ppProperty) { - // Check if the handle is valid - if (m_handle == INVALID_HANDLE_VALUE) { - return WHVPS_UNINITIALIZED; - } - - // Set the specified partition property - HRESULT hr = WHvSetPartitionProperty(m_handle, code, ppProperty, sizeof(WHV_PARTITION_PROPERTY)); - if (S_OK != hr) { - return WHVPS_FAILED; - } - return WHVPS_SUCCESS; -} - -WHvPartitionStatus WHvPartition::Setup() { - // Check if the handle is valid - if (m_handle == INVALID_HANDLE_VALUE) { - return WHVPS_UNINITIALIZED; - } - - // Setup the partition - HRESULT hr = WHvSetupPartition(m_handle); - if (S_OK != hr) { - return WHVPS_SETUP_FAILED; - } - - return WHVPS_SUCCESS; -} - -WHvPartitionStatus WHvPartition::MapGpaRange(void *memory, WHV_GUEST_PHYSICAL_ADDRESS address, UINT64 size, WHV_MAP_GPA_RANGE_FLAGS flags) { - // Check if the handle is valid - if (m_handle == INVALID_HANDLE_VALUE) { - return WHVPS_UNINITIALIZED; - } - - // Map the memory to the specified guest physical address range - HRESULT hr = WHvMapGpaRange(m_handle, memory, address, size, flags); - if (S_OK != hr) { - return WHVPS_FAILED; - } - - return WHVPS_SUCCESS; -} - -WHvPartitionStatus WHvPartition::UnmapGpaRange(WHV_GUEST_PHYSICAL_ADDRESS address, UINT64 size) { - // Check if the handle is valid - if (m_handle == INVALID_HANDLE_VALUE) { - return WHVPS_UNINITIALIZED; - } - - // Unmaps the specified guest physical address range - HRESULT hr = WHvUnmapGpaRange(m_handle, address, size); - if (S_OK != hr) { - return WHVPS_FAILED; - } - - return WHVPS_SUCCESS; -} - -WHvVCPUStatus WHvPartition::CreateVCPU(WHvVCPU **ppVcpu, UINT32 vpIndex) { - // Create and initialize the VCPU bound to this partition - WHvVCPU *vcpu = new WHvVCPU(m_handle, vpIndex); - WHvVCPUStatus status = vcpu->Initialize(); - if (status != WHVVCPUS_SUCCESS) { - delete vcpu; - return status; - } - - // Add it to the vector so that we can clean up later - m_vcpus.push_back(vcpu); - *ppVcpu = vcpu; - - return WHVVCPUS_SUCCESS; -} - -WHvVCPUStatus WHvPartition::DeleteVCPU(WHvVCPU **ppVcpu) { - // Null check the pointers - if (ppVcpu == nullptr) { - return WHVVCPUS_INVALID_POINTER; - } - if (*ppVcpu == nullptr) { - return WHVVCPUS_INVALID_POINTER; - } - - // Make sure the VCPU was created by this partition - if ((*ppVcpu)->m_partitionHandle != m_handle) { - return WHVVCPUS_INVALID_OWNER; - } - - // Try to close the VCPU - WHvVCPUStatus closeStatus = (*ppVcpu)->Close(); - if (closeStatus != WHVPS_SUCCESS) { - return closeStatus; - } - - // Remove it from the clean up vector - for (auto it = m_vcpus.begin(); it != m_vcpus.end(); it++) { - if (*it == *ppVcpu) { - m_vcpus.erase(it); - break; - } - } - - // Delete and clear the pointer - delete *ppVcpu; - *ppVcpu = nullptr; - - return WHVVCPUS_SUCCESS; -} - - -WHvVCPU::WHvVCPU(WHV_PARTITION_HANDLE hPartition, UINT32 vpIndex) - : m_partitionHandle(hPartition) - , m_vpIndex(vpIndex) - , m_initialized(false) - , m_emuHandle(INVALID_HANDLE_VALUE) - , m_ioPortCallback(nullptr) - , m_memoryCallback(nullptr) -{ -} - -WHvVCPU::~WHvVCPU() { - Close(); -} - -WHvVCPUStatus WHvVCPU::Close() { - // Fail if the VCPU is not initialized - if (!m_initialized) { - return WHVVCPUS_NOT_INITIALIZED; - } - - // Delete the VCPU - HRESULT hr = WHvEmulatorDestroyEmulator(m_emuHandle); - if (S_OK != hr) { - return WHVVCPUS_DESTROY_EMU_FAILED; - } - - // Mark as uninitialized - m_initialized = false; - - return WHVVCPUS_SUCCESS; -} - -WHvVCPUStatus WHvVCPU::Initialize() { - // Fail if the VCPU is already initialized - if (m_initialized) { - return WHVVCPUS_ALREADY_INITIALIZED; - } - - // Create the VCPU - HRESULT hr = WHvCreateVirtualProcessor(m_partitionHandle, m_vpIndex, 0); - if (S_OK != hr) { - return WHVVCPUS_CREATE_FAILED; - } - - WHV_EMULATOR_CALLBACKS callbacks; - callbacks.Size = sizeof(WHV_EMULATOR_CALLBACKS); - callbacks.Reserved = 0; - callbacks.WHvEmulatorGetVirtualProcessorRegisters = GetVirtualProcessorRegistersCallback; - callbacks.WHvEmulatorSetVirtualProcessorRegisters = SetVirtualProcessorRegistersCallback; - callbacks.WHvEmulatorTranslateGvaPage = TranslateGvaPageCallback; - callbacks.WHvEmulatorIoPortCallback = IoPortCallback; - callbacks.WHvEmulatorMemoryCallback = MemoryCallback; - hr = WHvEmulatorCreateEmulator(&callbacks, &m_emuHandle); - if (S_OK != hr) { - WHvDeleteVirtualProcessor(m_partitionHandle, m_vpIndex); - return WHVVCPUS_CREATE_EMU_FAILED; - } - - // Mark as initialized - m_initialized = true; - - return WHVVCPUS_SUCCESS; -} - -WHvVCPUStatus WHvVCPU::Run() { - // Run the virtual processor - HRESULT hr = WHvRunVirtualProcessor(m_partitionHandle, m_vpIndex, &m_exitContext, sizeof(m_exitContext)); - if (S_OK != hr) { - return WHVVCPUS_RUN_FAILED; - } - - switch (m_exitContext.ExitReason) { - case WHvRunVpExitReasonX64IoPortAccess: - { - WHV_EMULATOR_STATUS emuStatus; - hr = WHvEmulatorTryIoEmulation(m_emuHandle, this, &m_exitContext.VpContext, &m_exitContext.IoPortAccess, &emuStatus); - if (S_OK != hr) { - return WHVVCPUS_EMULATION_FAILED; - } - if (!emuStatus.EmulationSuccessful) { - return WHVVCPUS_EMULATION_FAILED; - } - break; - } - case WHvRunVpExitReasonMemoryAccess: - { - WHV_EMULATOR_STATUS emuStatus; - hr = WHvEmulatorTryMmioEmulation(m_emuHandle, this, &m_exitContext.VpContext, &m_exitContext.MemoryAccess, &emuStatus); - if (S_OK != hr) { - return WHVVCPUS_EMULATION_FAILED; - } - if (!emuStatus.EmulationSuccessful) { - return WHVVCPUS_EMULATION_FAILED; - } - break; - } - } - - return WHVVCPUS_SUCCESS; -} - -WHvVCPUStatus WHvVCPU::CancelRun() { - // Cancel the virtual processor execution - HRESULT hr = WHvCancelRunVirtualProcessor(m_partitionHandle, m_vpIndex, 0); - if (S_OK != hr) { - return WHVVCPUS_FAILED; - } - - return WHVVCPUS_SUCCESS; -} - -WHvVCPUStatus WHvVCPU::GetRegisters(const WHV_REGISTER_NAME *regs, UINT32 count, WHV_REGISTER_VALUE *values) { - // Get specified registers - HRESULT hr = WHvGetVirtualProcessorRegisters(m_partitionHandle, m_vpIndex, regs, count, values); - if (S_OK != hr) { - return WHVVCPUS_GET_REGS_FAILED; - } - - return WHVVCPUS_SUCCESS; -} - -WHvVCPUStatus WHvVCPU::SetRegisters(const WHV_REGISTER_NAME *regs, UINT32 count, const WHV_REGISTER_VALUE *values) { - // Set specified registers - HRESULT hr = WHvSetVirtualProcessorRegisters(m_partitionHandle, m_vpIndex, regs, count, values); - if (S_OK != hr) { - return WHVVCPUS_SET_REGS_FAILED; - } - - return WHVVCPUS_SUCCESS; -} - -WHvVCPUStatus WHvVCPU::Interrupt(uint16_t vector) { - WHV_REGISTER_NAME regs[] = { - WHvRegisterPendingInterruption, - }; - WHV_REGISTER_VALUE vals[sizeof(regs) / sizeof(regs[0])]; - WHvVCPUStatus vcpuStatus = GetRegisters(regs, sizeof(regs) / sizeof(regs[0]), vals); - if (WHVVCPUS_SUCCESS != vcpuStatus) { - return vcpuStatus; - } - - // Setup the interrupt - vals[0].PendingInterruption.InterruptionPending = TRUE; - vals[0].PendingInterruption.InterruptionType = WHvX64PendingInterrupt; - vals[0].PendingInterruption.InterruptionVector = vector; - - vcpuStatus = SetRegisters(regs, sizeof(regs) / sizeof(regs[0]), vals); - if (WHVVCPUS_SUCCESS != vcpuStatus) { - return vcpuStatus; - } - - return WHVVCPUS_SUCCESS; -} - -HRESULT WHvVCPU::GetVirtualProcessorRegistersCallback( - VOID* Context, - const WHV_REGISTER_NAME* RegisterNames, - UINT32 RegisterCount, - WHV_REGISTER_VALUE* RegisterValues -) { - WHvVCPU *vcpu = (WHvVCPU *) Context; - return WHvGetVirtualProcessorRegisters(vcpu->m_partitionHandle, vcpu->m_vpIndex, RegisterNames, RegisterCount, RegisterValues); -} - -HRESULT WHvVCPU::SetVirtualProcessorRegistersCallback( - VOID* Context, - const WHV_REGISTER_NAME* RegisterNames, - UINT32 RegisterCount, - const WHV_REGISTER_VALUE* RegisterValues -) { - WHvVCPU *vcpu = (WHvVCPU *) Context; - return WHvSetVirtualProcessorRegisters(vcpu->m_partitionHandle, vcpu->m_vpIndex, RegisterNames, RegisterCount, RegisterValues); -} - -HRESULT WHvVCPU::TranslateGvaPageCallback(VOID* Context, WHV_GUEST_VIRTUAL_ADDRESS Gva, WHV_TRANSLATE_GVA_FLAGS TranslateFlags, WHV_TRANSLATE_GVA_RESULT_CODE* TranslationResult, WHV_GUEST_PHYSICAL_ADDRESS* Gpa) { - WHvVCPU *vcpu = (WHvVCPU *)Context; - WHV_TRANSLATE_GVA_RESULT result; - HRESULT hr = WHvTranslateGva(vcpu->m_partitionHandle, vcpu->m_vpIndex, Gva, TranslateFlags, &result, Gpa); - if (S_OK == hr) { - *TranslationResult = result.ResultCode; - } - return hr; -} - -HRESULT WHvVCPU::IoPortCallback(VOID *Context, WHV_EMULATOR_IO_ACCESS_INFO *IoAccess) { - WHvVCPU *vcpu = (WHvVCPU *)Context; - if (vcpu->m_ioPortCallback == nullptr) { - return E_NOTIMPL; - } - return vcpu->m_ioPortCallback(Context, IoAccess); -} - -HRESULT WHvVCPU::MemoryCallback(VOID *Context, WHV_EMULATOR_MEMORY_ACCESS_INFO *MemoryAccess) { - WHvVCPU *vcpu = (WHvVCPU *)Context; - if (vcpu->m_memoryCallback == nullptr) { - return E_NOTIMPL; - } - return vcpu->m_memoryCallback(Context, MemoryAccess); -} diff --git a/src/cpu-module-whvp/whvp/whvp.h b/src/cpu-module-whvp/whvp/whvp.h deleted file mode 100644 index d6ed067..0000000 --- a/src/cpu-module-whvp/whvp/whvp.h +++ /dev/null @@ -1,149 +0,0 @@ -#pragma once - -#include -#include -#include - -#include - -enum WHvStatus { - WHVS_SUCCESS = 0, // The operation completed successfully - - WHVS_FAILED = 0x80000000, // The operation failed - WHVS_INVALID_CAPABILITY, // An invalid capability code was passed -}; - -enum WHvPartitionStatus { - WHVPS_SUCCESS = 0, // Partition created successfully - - WHVPS_FAILED = 0x80000000, // The operation failed - WHVPS_CREATE_FAILED, // Failed to create partition - WHVPS_DELETE_FAILED, // Failed to delete a partition - WHVPS_SETUP_FAILED, // Failed to setup a partition - WHVPS_ALREADY_CREATED, // Attempted to create a partition that was already created - WHVPS_ALREADY_DELETED, // Attempted to delete a partition that was already deleted - WHVPS_INVALID_OWNER, // Attempted to delete a partition that does not belong to the platform object - WHVPS_INVALID_POINTER, // An invalid pointer to a partition was passed to a function - WHVPS_UNINITIALIZED, // The partition is not initialized -}; - -enum WHvVCPUStatus { - WHVVCPUS_SUCCESS = 0, // VCPU created successfully - - WHVVCPUS_FAILED = 0x80000000, // The operation failed - WHVVCPUS_CREATE_FAILED, // Failed to create VCPU - WHVVCPUS_CREATE_EMU_FAILED, // Failed to create instruction emulator - WHVVCPUS_DESTROY_EMU_FAILED, // Failed to destroy the instruction emulator - WHVVCPUS_NOT_INITIALIZED, // Attempted to delete an uninitialized VCPU - WHVVCPUS_ALREADY_INITIALIZED, // Attempted to create an initialized VCPU - WHVVCPUS_INVALID_POINTER, // An invalid pointer to a VCPU was passed to a function - WHVVCPUS_INVALID_OWNER, // Attempted to delete a VCPU that does not belong to the partition - WHVVCPUS_GET_REGS_FAILED, // Failed to get registers - WHVVCPUS_SET_REGS_FAILED, // Failed to set registers - WHVVCPUS_RUN_FAILED, // VCPU execution failed - WHVVCPUS_EMULATION_FAILED, // VCPU instruction emulation failed -}; - - -#define WHV_IO_IN 0 -#define WHV_IO_OUT 1 - - -class WHvPartition; -class WHvVCPU; - -class WinHvPlatform { -public: - WinHvPlatform(); - ~WinHvPlatform(); - - const bool IsPresent() const { return m_present; } - - WHvStatus GetCapability(WHV_CAPABILITY_CODE code, WHV_CAPABILITY *pCap); - - WHvPartitionStatus CreatePartition(WHvPartition **ppPartition); - WHvPartitionStatus DeletePartition(WHvPartition **ppPartition); - -private: - bool m_present; - - std::vector m_partitions; -}; - - -class WHvPartition { -public: - WHvPartitionStatus GetProperty(WHV_PARTITION_PROPERTY_CODE code, WHV_PARTITION_PROPERTY *ppProperty); - WHvPartitionStatus SetProperty(WHV_PARTITION_PROPERTY_CODE code, WHV_PARTITION_PROPERTY *ppProperty); - - WHvPartitionStatus Setup(); - - WHvPartitionStatus MapGpaRange(void *memory, WHV_GUEST_PHYSICAL_ADDRESS address, UINT64 size, WHV_MAP_GPA_RANGE_FLAGS flags); - WHvPartitionStatus UnmapGpaRange(WHV_GUEST_PHYSICAL_ADDRESS address, UINT64 size); - - WHvVCPUStatus CreateVCPU(WHvVCPU **ppVcpu, UINT32 vpIndex); - WHvVCPUStatus DeleteVCPU(WHvVCPU **ppVcpu); - - WHvPartitionStatus Close(); - -private: - WHvPartition(WinHvPlatform *platform); - ~WHvPartition(); - - WHvPartitionStatus Initialize(); - - WinHvPlatform *m_platform; - WHV_PARTITION_HANDLE m_handle; - - std::vector m_vcpus; - - friend class WinHvPlatform; -}; - - -typedef HRESULT (CALLBACK *WHvIoPortCallback)(PVOID Context, WHV_EMULATOR_IO_ACCESS_INFO* IoAccess); -typedef HRESULT (CALLBACK *WHvMemoryCallback)(PVOID Context, WHV_EMULATOR_MEMORY_ACCESS_INFO* MemoryAccess); - -class WHvVCPU { -public: - WHvVCPUStatus Run(); - WHvVCPUStatus CancelRun(); - - WHvVCPUStatus Interrupt(uint16_t vector); - - WHvVCPUStatus GetRegisters(const WHV_REGISTER_NAME *regs, UINT32 count, WHV_REGISTER_VALUE *values); - WHvVCPUStatus SetRegisters(const WHV_REGISTER_NAME *regs, UINT32 count, const WHV_REGISTER_VALUE *values); - - WHvVCPUStatus Close(); - - const WHV_RUN_VP_EXIT_CONTEXT * ExitContext() const { return &m_exitContext; } - - void SetIoPortCallback(WHvIoPortCallback ioPortCallback) { m_ioPortCallback = ioPortCallback; } - void SetMemoryCallback(WHvMemoryCallback memoryCallback) { m_memoryCallback = memoryCallback; } - -private: - WHvVCPU(WHV_PARTITION_HANDLE hPartition, UINT32 vpIndex); - ~WHvVCPU(); - - WHvVCPUStatus Initialize(); - - bool m_initialized; - - WHV_PARTITION_HANDLE m_partitionHandle; - UINT32 m_vpIndex; - WHV_RUN_VP_EXIT_CONTEXT m_exitContext; - - WHV_EMULATOR_HANDLE m_emuHandle; - WHvIoPortCallback m_ioPortCallback; - WHvMemoryCallback m_memoryCallback; - - - static HRESULT GetVirtualProcessorRegistersCallback(VOID* Context, const WHV_REGISTER_NAME* RegisterNames, UINT32 RegisterCount, WHV_REGISTER_VALUE* RegisterValues); - static HRESULT SetVirtualProcessorRegistersCallback(VOID* Context, const WHV_REGISTER_NAME* RegisterNames, UINT32 RegisterCount, const WHV_REGISTER_VALUE* RegisterValues); - static HRESULT TranslateGvaPageCallback(VOID* Context, WHV_GUEST_VIRTUAL_ADDRESS Gva, WHV_TRANSLATE_GVA_FLAGS TranslateFlags, WHV_TRANSLATE_GVA_RESULT_CODE* TranslationResult, WHV_GUEST_PHYSICAL_ADDRESS* Gpa); - static HRESULT IoPortCallback(VOID* Context, WHV_EMULATOR_IO_ACCESS_INFO* IoAccess); - static HRESULT MemoryCallback(VOID* Context, WHV_EMULATOR_MEMORY_ACCESS_INFO* MemoryAccess); - - - friend class WHvPartition; -}; diff --git a/src/cpu-module/CMakeLists.txt b/src/cpu-module/CMakeLists.txt deleted file mode 100644 index e56b484..0000000 --- a/src/cpu-module/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -# Add sources -file(GLOB DIR_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/vixen/*.h - ) - -file(GLOB DIR_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/vixen/*.cpp - ) - -set(SOURCES ${SOURCES} - ${DIR_HEADERS} - ${DIR_SOURCES} - ) - -# Add Visual Studio filters to better organize the code -vs_set_filters("${SOURCES}" "vixen") - -# Main Executable -if(NOT MSVC) - add_definitions("-Wall -Werror -O0 -g -fPIC") -endif() - -add_library(cpu-module STATIC "${SOURCES}") -target_include_directories(cpu-module PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - -# Include viXen common module code -target_link_libraries(cpu-module module-common) - -# Make the Debug and RelWithDebInfo targets use Program Database for Edit and Continue for easier debugging -vs_use_edit_and_continue() - diff --git a/src/cpu-module/vixen/cpu.cpp b/src/cpu-module/vixen/cpu.cpp deleted file mode 100644 index 864957a..0000000 --- a/src/cpu-module/vixen/cpu.cpp +++ /dev/null @@ -1,462 +0,0 @@ -#include -#include - -#include "vixen/cpu.h" -#include "vixen/log.h" -#include "vixen/pte.h" - -namespace vixen { -namespace cpu { - -#define KB 1024 -#define MB KB*KB -#define PAGE_SIZE 4*KB -#define PAGE_SIZE_LARGE 4*MB -#define PAGE_SHIFT 12 - -Cpu::Cpu() { -} - -Cpu::~Cpu() { - // Clear the physical memory map - for (auto it = m_physMemMap.begin(); it != m_physMemMap.end(); it++) { - delete *it; - } - m_physMemMap.clear(); -} - -// ----- Basic CPU operations ------------------------------------------------- - -CPUInitStatus Cpu::Initialize(IOMapper *ioMapper) { - m_ioMapper = ioMapper; - - m_interruptHandlerCredits = kInterruptHandlerMaxCredits; - - return InitializeImpl(); -} - -#define CHECK_RESULT(expr) do { CPUOperationStatus result = (expr); { if (result != CPUS_OP_OK) return result; } } while (0) - -CPUStatus Cpu::Run() { - HandleInterruptQueue(); - return RunImpl(); -} - -CPUStatus Cpu::Step() { - HandleInterruptQueue(); - return StepImpl(); -} - -CPUStatus Cpu::StepImpl() { - return CPUS_UNSUPPORTED; -} - -InterruptResult Cpu::Interrupt(uint8_t vector) { - // Acquire the pending interrupts mutex - std::lock_guard guard(m_pendingInterruptsMutex); - - // Enqueue the interrupt - m_pendingInterrupts.push(vector); - - return InterruptImpl(vector); -} - -// ----- Physical memory ------------------------------------------------------ - -CPUMemMapStatus Cpu::MemMap(MemoryRegion *mem) { - // FIXME: We should flatten out the address space to handle sub-sub regions - - assert(mem->m_start == 0); - - for (auto it = mem->m_subregions; it != nullptr; it = it->next) { - auto subregion = it->curr; - log_debug("Mapping Region %08x - %08zx\n", subregion->m_start, subregion->m_start + subregion->m_size - 1); - CPUMemMapStatus status = MemMapSubregion(subregion); - if (status != CPUS_MMAP_OK) { - log_error(" Failed to map subregion\n"); - return status; - } - - // Map the physical address range if valid - if (subregion->m_type == MEM_REGION_RAM || subregion->m_type == MEM_REGION_ROM) { - m_physMemMap.push_back(new PhysicalMemoryRange{ (char *)subregion->m_data, subregion->m_start, subregion->m_start + (uint32_t)subregion->m_size - 1 }); - } - } - return CPUS_MMAP_OK; -} - -CPUOperationStatus Cpu::MemRead(uint32_t addr, uint32_t size, void *value) { - for (auto it = m_physMemMap.begin(); it != m_physMemMap.end(); it++) { - auto physMemRegion = *it; - if (addr >= physMemRegion->startingAddress && addr + size - 1 <= physMemRegion->endingAddress) { - memcpy(value, &physMemRegion->data[addr - physMemRegion->startingAddress], size); - return CPUS_OP_OK; - } - } - - return CPUS_OP_INVALID_ADDRESS; -} - -CPUOperationStatus Cpu::MemWrite(uint32_t addr, uint32_t size, void *value) { - for (auto it = m_physMemMap.begin(); it != m_physMemMap.end(); it++) { - auto physMemRegion = *it; - if (addr >= physMemRegion->startingAddress && addr + size - 1 <= physMemRegion->endingAddress) { - memcpy(&physMemRegion->data[addr - physMemRegion->startingAddress], value, size); - return CPUS_OP_OK; - } - } - - return CPUS_OP_INVALID_ADDRESS; -} - -// ----- Virtual memory ------------------------------------------------------- - -bool Cpu::VirtualToPhysical(uint32_t vaddr, uint32_t *paddr) { - // TODO: check MTRR - - // Get the PDE table address - uint32_t cr3; // TODO: cache cr3 value - RegRead(REG_CR3, &cr3); - - // Find the PDE entry corresponding to the given virtual address - uint32_t pdeOffset = (vaddr >> 22) << 2; - Pte pde; - MemRead(cr3 + pdeOffset, sizeof(Pte), &pde); - - // If the PDE uses large pages, it points to a 4 MB page - if (pde.largePage) { - *paddr = (pde.pageFrameNumber << PAGE_SHIFT) | (vaddr & (PAGE_SIZE_LARGE - 1)); - return true; - } - - // If the PDE is not valid, the virtual address is not valid - if (!pde.valid) { - return false; - } - - // Get the page where the PTE table corresponding to the PDE is located - uint32_t pteTableAddr = (pde.pageFrameNumber << PAGE_SHIFT); - - // Find the PTE entry - uint32_t pteOffset = ((vaddr << 10) >> 22) << 2; - Pte pte; - MemRead(pteTableAddr + pteOffset, sizeof(Pte), &pte); - - // If the PTE is not valid, the virtual address is not valid - if (!pte.valid) { - return false; - } - - // The physical address is located at the corresponding 4 KB page - *paddr = (pte.pageFrameNumber << PAGE_SHIFT) | (vaddr & (PAGE_SIZE - 1)); - return true; -} - -CPUOperationStatus Cpu::VMemRead(uint32_t vaddr, uint32_t size, void *value, uint32_t *bytesRead) { - uint32_t srcAddrStart = vaddr; - uint32_t srcAddrEnd = ((srcAddrStart + PAGE_SIZE) & ~(PAGE_SIZE - 1)) - 1; - uint32_t pos = 0; - uint32_t copySize = srcAddrEnd - srcAddrStart + 1; - if (size < copySize) { - copySize = size; - } - while (pos < size) { - uint32_t physAddr; - if (!VirtualToPhysical(srcAddrStart, &physAddr)) { - return CPUS_OP_INVALID_ADDRESS; - } - - CPUOperationStatus result = MemRead(physAddr, copySize, &((char*)value)[pos]); - if (result != CPUS_OP_OK) { - return result; - } - - pos += copySize; - srcAddrStart = srcAddrEnd + 1; - srcAddrEnd += PAGE_SIZE; - copySize = size - pos; - if (PAGE_SIZE < copySize) { - copySize = PAGE_SIZE; - } - } - - if (bytesRead != nullptr) { - *bytesRead = pos; - } - return CPUS_OP_OK; -} - -CPUOperationStatus Cpu::VMemWrite(uint32_t vaddr, uint32_t size, void *value, uint32_t *bytesWritten) { - uint32_t srcAddrStart = vaddr; - uint32_t srcAddrEnd = ((srcAddrStart + PAGE_SIZE) & ~(PAGE_SIZE - 1)) - 1; - uint32_t pos = 0; - uint32_t copySize = srcAddrEnd - srcAddrStart + 1; - if (size < copySize) { - copySize = size; - } - while (pos < size) { - uint32_t physAddr; - if (!VirtualToPhysical(srcAddrStart, &physAddr)) { - return CPUS_OP_INVALID_ADDRESS; - } - - CPUOperationStatus result = MemWrite(physAddr, copySize, &((char*)value)[pos]); - if (result != CPUS_OP_OK) { - return result; - } - - pos += copySize; - srcAddrStart = srcAddrEnd + 1; - srcAddrEnd += PAGE_SIZE; - copySize = size - pos; - if (PAGE_SIZE < copySize) { - copySize = PAGE_SIZE; - } - } - - if (bytesWritten != nullptr) { - *bytesWritten = pos; - } - return CPUS_OP_OK; -} - -// ----- Stack ---------------------------------------------------------------- - -CPUOperationStatus Cpu::CreateStackSpace(uint32_t size) { - uint32_t esp; - CHECK_RESULT(RegRead(REG_ESP, &esp)); - esp -= size; - CHECK_RESULT(RegWrite(REG_ESP, esp)); - return CPUS_OP_OK; -} - -CPUOperationStatus Cpu::ReclaimStackSpace(uint32_t size) { - uint32_t esp; - CHECK_RESULT(RegRead(REG_ESP, &esp)); - esp += size; - CHECK_RESULT(RegWrite(REG_ESP, esp)); - return CPUS_OP_OK; -} - -// ----- Registers ------------------------------------------------------------ - -CPUOperationStatus Cpu::RegCopy(enum CpuReg dst, enum CpuReg src) { - uint32_t tmp; - CHECK_RESULT(RegRead(src, &tmp)); - CHECK_RESULT(RegWrite(dst, tmp)); - return CPUS_OP_OK; -} - -CPUOperationStatus Cpu::RegRead(CpuReg regs[], uint32_t values[], uint8_t numRegs) { - for (uint8_t i = 0; i < numRegs; i++) { - CPUOperationStatus status = RegRead(regs[i], &values[i]); - if (status != CPUS_OP_OK) { - return status; - } - } - return CPUS_OP_OK; -} - -CPUOperationStatus Cpu::RegWrite(CpuReg regs[], uint32_t values[], uint8_t numRegs) { - for (uint8_t i = 0; i < numRegs; i++) { - CPUOperationStatus status = RegWrite(regs[i], values[i]); - if (status != CPUS_OP_OK) { - return status; - } - } - return CPUS_OP_OK; -} - -CPUOperationStatus Cpu::RegCopy(CpuReg dsts[], CpuReg srcs[], uint8_t numRegs) { - for (uint8_t i = 0; i < numRegs; i++) { - CPUOperationStatus status = RegCopy(dsts[i], srcs[i]); - if (status != CPUS_OP_OK) { - return status; - } - } - return CPUS_OP_OK; -} - -CPUOperationStatus Cpu::GetGDTEntry(uint16_t selector, GDTEntry *entry) { - uint32_t base; - uint32_t limit; - CHECK_RESULT(GetGDT(&base, &limit)); - if (selector + sizeof(GDTEntry) > limit) { - return CPUS_OP_INVALID_SELECTOR; - } - CHECK_RESULT(MemRead(base + selector, sizeof(GDTEntry), entry)); - return CPUS_OP_OK; -} - -CPUOperationStatus Cpu::SetGDTEntry(uint16_t selector, GDTEntry *entry) { - uint32_t base; - uint32_t limit; - CHECK_RESULT(GetGDT(&base, &limit)); - if (selector + sizeof(GDTEntry) > limit) { - return CPUS_OP_INVALID_SELECTOR; - } - CHECK_RESULT(MemWrite(base + selector, sizeof(GDTEntry), entry)); - return CPUS_OP_OK; -} - -CPUOperationStatus Cpu::GetIDTEntry(uint8_t vector, IDTEntry *entry) { - uint32_t base; - uint32_t limit; - CHECK_RESULT(GetIDT(&base, &limit)); - if (vector * sizeof(IDTEntry) > limit) { - return CPUS_OP_INVALID_SELECTOR; - } - CHECK_RESULT(MemRead(base + vector * sizeof(IDTEntry), sizeof(IDTEntry), entry)); - return CPUS_OP_OK; -} - -CPUOperationStatus Cpu::SetIDTEntry(uint8_t vector, IDTEntry *entry) { - uint32_t base; - uint32_t limit; - CHECK_RESULT(GetIDT(&base, &limit)); - if (vector * sizeof(IDTEntry) > limit) { - return CPUS_OP_INVALID_SELECTOR; - } - CHECK_RESULT(MemWrite(base + vector * sizeof(IDTEntry), sizeof(IDTEntry), entry)); - return CPUS_OP_OK; -} - -CPUOperationStatus Cpu::SetInterruptsEnabled(bool enabled) { - uint32_t flags; - CHECK_RESULT(RegRead(REG_EFLAGS, &flags)); - if (enabled) { - flags |= IF_MASK; - } - else { - flags &= ~IF_MASK; - } - CHECK_RESULT(RegWrite(REG_EFLAGS, flags)); - return CPUS_OP_OK; -} - -CPUOperationStatus Cpu::SetFlags(uint32_t flagsBits) { - uint32_t flags; - CHECK_RESULT(RegRead(REG_EFLAGS, &flags)); - flags |= flagsBits; - CHECK_RESULT(RegWrite(REG_EFLAGS, flags)); - return CPUS_OP_OK; -} - -CPUOperationStatus Cpu::ClearFlags(uint32_t flagsBits) { - uint32_t flags; - CHECK_RESULT(RegRead(REG_EFLAGS, &flags)); - flags &= ~flagsBits; - CHECK_RESULT(RegWrite(REG_EFLAGS, flags)); - return CPUS_OP_OK; -} - -// ----- Instructions --------------------------------------------------------- - -CPUOperationStatus Cpu::Push(uint32_t value) { - uint32_t esp; - CHECK_RESULT(RegRead(REG_ESP, &esp)); - esp -= 4; - CHECK_RESULT(VMemWrite(esp, 4, &value)); - CHECK_RESULT(RegWrite(REG_ESP, esp)); - return CPUS_OP_OK; -} - -CPUOperationStatus Cpu::PushReg(enum CpuReg reg) { - uint32_t value; - CHECK_RESULT(RegRead(reg, &value)); - CHECK_RESULT(Push(value)); - return CPUS_OP_OK; -} - -CPUOperationStatus Cpu::PushFlags() { - return PushReg(REG_EFLAGS); -} - -CPUOperationStatus Cpu::Pop(uint32_t *value) { - uint32_t esp; - CHECK_RESULT(RegRead(REG_ESP, &esp)); - CHECK_RESULT(VMemRead(esp, 4, value)); - esp += 4; - CHECK_RESULT(RegWrite(REG_ESP, esp)); - return CPUS_OP_OK; -} - -CPUOperationStatus Cpu::PopReg(enum CpuReg reg) { - uint32_t value; - CHECK_RESULT(Pop(&value)); - CHECK_RESULT(RegWrite(reg, value)); - return CPUS_OP_OK; -} - -CPUOperationStatus Cpu::PopFlags() { - return PopReg(REG_EFLAGS); -} - -CPUOperationStatus Cpu::Ret() { - return PopReg(REG_EIP); -} - -CPUOperationStatus Cpu::EnableSoftwareBreakpoints(bool enable) { - return CPUS_OP_UNSUPPORTED; -} - -CPUOperationStatus Cpu::SetHardwareBreakpoints(HardwareBreakpoints breakpoints) { - return CPUS_OP_UNSUPPORTED; -} - -CPUOperationStatus Cpu::ClearHardwareBreakpoints() { - return CPUS_OP_UNSUPPORTED; -} - -CPUOperationStatus Cpu::GetBreakpointAddress(uint32_t *address) { - return CPUS_OP_UNSUPPORTED; -} - -void Cpu::HandleInterruptQueue() { - // Increment the credits available for the interrupt handler - if (m_interruptHandlerCredits < kInterruptHandlerMaxCredits) { - m_interruptHandlerCredits += kInterruptHandlerIncrement; - } - - // Inject an interrupt if available and possible - if (m_pendingInterrupts.size() > 0) { - if (CanInjectInterrupt()) { - InjectPendingInterrupt(); - } - // Request an interrupt window if the VCPU is not ready - else { - RequestInterruptWindow(); - } - } -} - -void Cpu::InjectPendingInterrupt() { - // If there aren't enough credits or there are no pending interrupts, get out - if (m_interruptHandlerCredits < kInterruptHandlerCost || m_pendingInterrupts.size() == 0) { - return; - } - - // Spend the credits and handle one interrupt - m_interruptHandlerCredits -= kInterruptHandlerCost; - - // Acquire the pending interrupts mutex - std::lock_guard guard(m_pendingInterruptsMutex); - - // Dequeue the next interrupt vector - uint8_t vector = m_pendingInterrupts.front(); - m_pendingInterrupts.pop(); - -#ifdef _DEBUG - if (m_pendingInterrupts.size() > 100) { - log_warning("Pending interrupts queue growing too long!\n"); - } -#endif - - // Inject the interrupt into the VCPU - InjectInterrupt(vector); - - return; -} - -} -} diff --git a/src/cpu-module/vixen/cpu.h b/src/cpu-module/vixen/cpu.h deleted file mode 100644 index 8af428e..0000000 --- a/src/cpu-module/vixen/cpu.h +++ /dev/null @@ -1,541 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include "vixen/memregion.h" -#include "vixen/gdt.h" -#include "vixen/idt.h" -#include "vixen/io.h" -#include "vixen/status.h" - -namespace vixen { -namespace cpu { - -// These constants control how often the CPU can handle interrupts, while -// giving some affordance to handle short bursts. -// Without this, the emulator might get stuck processing interrupts alone. -#ifdef _DEBUG -static const uint8_t kInterruptHandlerMaxCredits = 25; // Maximum amount of credits available to handle interrupts -static const uint8_t kInterruptHandlerCost = 5; // Credits spent when an interrupt is handled -static const uint8_t kInterruptHandlerIncrement = 1; // Credits recovered when CPU emulation starts -#else -static const uint8_t kInterruptHandlerMaxCredits = 200; // Maximum amount of credits available to handle interrupts -static const uint8_t kInterruptHandlerCost = 2; // Credits spent when an interrupt is handled -static const uint8_t kInterruptHandlerIncrement = 1; // Credits recovered when CPU emulation starts -#endif - - -// CR0 bits -#define CR0_PG 0x80000000 // paging -#define CR0_CD 0x40000000 // cache disable -#define CR0_NW 0x20000000 // not write-through -#define CR0_AM 0x00040000 // alignment mask -#define CR0_WP 0x00010000 // write protect -#define CR0_NE 0x00000020 // numeric error -#define CR0_ET 0x00000010 // extension type (80387) -#define CR0_TS 0x00000008 // task switched -#define CR0_EM 0x00000004 // emulate math coprocessor -#define CR0_MP 0x00000002 // math present -#define CR0_PE 0x00000001 // protection enable - -// CR4 bits -#define CR4_VME 0x00000001 // V86 mode extensions -#define CR4_PVI 0x00000002 // Protected mode virtual interrupts -#define CR4_TSD 0x00000004 // Time stamp disable -#define CR4_DE 0x00000008 // Debugging Extensions -#define CR4_PSE 0x00000010 // Page size extensions -#define CR4_PAE 0x00000020 // Physical address extensions -#define CR4_MCE 0x00000040 // Machine check enable -#define CR4_PGE 0x00000080 // Page global enable -#define CR4_FXSR 0x00000200 // FXSR used by OS -#define CR4_XMMEXCPT 0x00000400 // XMMI used by OS - -// EFLAGS -#define CF_BIT 0 // Carry flag -#define CF_MASK (1 << CF_BIT) -#define PF_BIT 2 // Parity flag -#define PF_MASK (1 << PF_BIT) -#define AF_BIT 4 // Adjust flag -#define AF_MASK (1 << AF_BIT) -#define ZF_BIT 6 // Zero flag -#define ZF_MASK (1 << ZF_BIT) -#define SF_BIT 7 // Sign flag -#define SF_MASK (1 << SF_BIT) -#define TF_BIT 8 // Trap flag -#define TF_MASK (1 << TF_BIT) -#define IF_BIT 9 // Interrupt flag -#define IF_MASK (1 << IF_BIT) -#define DF_BIT 10 // Direction flag -#define DF_MASK (1 << DF_BIT) -#define OF_BIT 11 // Overflow flag -#define OF_MASK (1 << OF_BIT) -#define IOPL_MASK 0x3000 // IO privilege level -#define IOPL_BIT0 12 -#define IOPL_BIT1 13 -#define NT_BIT 14 // Nested task -#define NT_MASK (1 << NT_BIT) -#define RF_BIT 16 // Resume flag -#define RF_MASK (1 << RF_BIT) -#define VM_BIT 17 // Virtual Mode -#define VM_MASK (1 << VM_BIT) -#define AC_BIT 18 // Alignment check -#define AC_MASK (1 << AC_BIT) -#define VIF_BIT 19 // Virtual Interrupt flag -#define VIF_MASK (1 << VIF_BIT) -#define VIP_BIT 20 // Virtual Interrupt pending -#define VIP_MASK (1 << VIP_BIT) - - -/*! - * Enumeration type for standard registers - */ -enum CpuReg { - REG_EIP, - REG_EFLAGS, - REG_EAX, - REG_ECX, - REG_EDX, - REG_EBX, - REG_ESI, - REG_EDI, - REG_ESP, - REG_EBP, - REG_CS, - REG_SS, - REG_DS, - REG_ES, - REG_FS, - REG_GS, - REG_TR, - REG_CR0, - REG_CR2, - REG_CR3, - REG_CR4, - // TODO: add floating-point, MMX and SSE registers - REG_MAX, -}; - -// Last register to save in CpuContext -#define REG_CONTEXT_MAX ((size_t)(REG_GDT_LIMIT + 1)) - -/*! - * Exit Info - */ -enum CpuExitReason { - CPU_EXIT_NORMAL, // Time slice expiration - CPU_EXIT_ERROR, // Non-specific error - CPU_EXIT_INTERRUPT, // Interrupt - CPU_EXIT_HLT, // HLT instruction - CPU_EXIT_SHUTDOWN, // System shutdown - CPU_EXIT_SW_BREAKPOINT, // Software breakpoint - CPU_EXIT_HW_BREAKPOINT, // Hardware breakpoint -}; - -enum InterruptResult { - INTR_SUCCESS, // The interrupt was successfully delivered to the CPU - INTR_DISABLED, // The interrupt was not delivered because interrupts are disabled - INTR_MASKED, // The interrupt was masked by the CPU - INTR_PENDING, // There is an unhandled pending interrupt from a previous interrupt call - INTR_FAILED, // Interrupt handling failed - INTR_NO_HANDLER, // No interrupt handler was specified -}; - -struct CpuExitInfo { - enum CpuExitReason reason; - uint8_t intr_vector; -}; - -typedef void (*InterruptHandlerFunc)(uint8_t vector, void *data); - -struct PhysicalMemoryRange { - char *data; - uint32_t startingAddress; - uint32_t endingAddress; -}; - -enum HardwareBreakpointTrigger { - HWBP_TRIGGER_EXECUTION = 0, - HWBP_TRIGGER_DATA_WRITE, - HWBP_TRIGGER_8_BYTE_WIDE, - HWBP_TRIGGER_DATA_READ_WRITE, -}; - -enum HardwareBreakpointLength { - HWBP_LENGTH_1_BYTE = 0, - HWBP_LENGTH_2_BYTE, - HWBP_LENGTH_8_BYTE, - HWBP_LENGTH_4_BYTE, -}; - -struct HardwareBreakpoints { - struct { - uint64_t address; - bool localEnable; - bool globalEnable; - HardwareBreakpointTrigger trigger; - HardwareBreakpointLength length; - } bp[4]; -}; - -/*! - * CPU base class - * - * Defines a basic interface for the CPU that will be subclassed by actual - * implementations. - */ -class Cpu { -public: - // Constructor. - Cpu(); - - // Destructor. - virtual ~Cpu(); - - // ----- Basic CPU operations --------------------------------------------- - - /*! - * Initializes the CPU. - */ - CPUInitStatus Initialize(IOMapper *ioMapper); - - /*! - * Runs the CPU until interrupted. - */ - CPUStatus Run(); - - /*! - * Runs one instruction on the CPU. - * - * This is an optional operation. TODO: implement capability checking. - */ - CPUStatus Step(); - - /*! - * Sends an interrupt to the CPU, optionally making it non maskable. - * - * If interrupts are disabled, returns INTR_DISABLED. - * If the interrupt was masked, returns INTR_MASKED. - * Otherwise it enqueues the interrupt request, stops CPU emulation and - * returns INTR_SUCCESS. - */ - InterruptResult Interrupt(uint8_t vector); - - // ----- Physical memory -------------------------------------------------- - - /*! - * Maps memory regions, including optional memory access handlers. - */ - CPUMemMapStatus MemMap(MemoryRegion *mem); - - /*! - * Maps a memory subregion. - */ - virtual CPUMemMapStatus MemMapSubregion(MemoryRegion *subregion) = 0; - - /*! - * Reads a portion of physical memory into the specified value. - */ - CPUOperationStatus MemRead(uint32_t addr, uint32_t size, void *value); - - /*! - * Writes the specified value into physical memory. - */ - CPUOperationStatus MemWrite(uint32_t addr, uint32_t size, void *value); - - // ----- Virtual memory --------------------------------------------------- - - /*! - * Maps a virtual address to a physical address. Returns true if the - * mapping is valid. - */ - bool VirtualToPhysical(uint32_t vaddr, uint32_t *paddr); - - /*! - * Reads a portion of virtual memory into the specified value. x86 virtual - * address translation is performed based on the current registers and - * memory contents. Optionally, the caller may receive the number of bytes - * read during the operation. - */ - CPUOperationStatus VMemRead(uint32_t vaddr, uint32_t size, void *value, uint32_t *bytesRead = nullptr); - - /*! - * Writes the specified value into virtual memory. x86 virtual address - * translation is performed based on the current registers and memory - * contents. Optionally, the caller may receive the number of bytes written - * during the operation. - */ - CPUOperationStatus VMemWrite(uint32_t vaddr, uint32_t size, void *value, uint32_t *bytesWritten = nullptr); - - // ----- Stack ------------------------------------------------------------ - - /*! - * Creates space in the stack by subtracting the size from ESP. - */ - CPUOperationStatus CreateStackSpace(uint32_t size); - - /* - * Reclaims space in the stack by adding the size to ESP. - */ - CPUOperationStatus ReclaimStackSpace(uint32_t size); - - // ----- Registers -------------------------------------------------------- - - /*! - * Reads from a register. - */ - virtual CPUOperationStatus RegRead(enum CpuReg reg, uint32_t *value) = 0; - - /*! - * Writes to a register. - */ - virtual CPUOperationStatus RegWrite(enum CpuReg reg, uint32_t value) = 0; - - /*! - * Copies the value from the source register to the destination register. - */ - CPUOperationStatus RegCopy(enum CpuReg dst, enum CpuReg src); - - /*! - * Reads from registers in bulk. - */ - virtual CPUOperationStatus RegRead(enum CpuReg regs[], uint32_t values[], uint8_t numRegs); - - /*! - * Writes to registers in bulk. - */ - virtual CPUOperationStatus RegWrite(enum CpuReg regs[], uint32_t values[], uint8_t numRegs); - - /*! - * Copies the values from the source registers to the destination registers - * in bulk. - */ - CPUOperationStatus RegCopy(enum CpuReg dsts[], enum CpuReg srcs[], uint8_t numRegs); - - /*! - * Gets the Global Descriptor Table. - */ - virtual CPUOperationStatus GetGDT(uint32_t *base, uint32_t *limit) = 0; - - /*! - * Sets the Global Descriptor Table. - */ - virtual CPUOperationStatus SetGDT(uint32_t base, uint32_t limit) = 0; - - /*! - * Retrieves an entry in the Global Descriptor Table. - * Returns zero on success, non-zero if the index is out of bounds. - */ - CPUOperationStatus GetGDTEntry(uint16_t selector, GDTEntry *entry); - - /*! - * Modifies an entry in the Global Descriptor Table. - * Returns zero on success, non-zero if the index is out of bounds. - */ - CPUOperationStatus SetGDTEntry(uint16_t selector, GDTEntry *entry); - - /*! - * Gets the Interrupt Descriptor Table. - */ - virtual CPUOperationStatus GetIDT(uint32_t *base, uint32_t *limit) = 0; - - /*! - * Sets the Interrupt Descriptor Table. - */ - virtual CPUOperationStatus SetIDT(uint32_t base, uint32_t limit) = 0; - - /*! - * Retrieves an entry in the Interrupt Descriptor Table. - * Returns zero on success, non-zero if the index is out of bounds. - */ - CPUOperationStatus GetIDTEntry(uint8_t vector, IDTEntry *entry); - - /*! - * Modifies an entry in the Interrupt Descriptor Table. - * Returns zero on success, non-zero if the index is out of bounds. - */ - CPUOperationStatus SetIDTEntry(uint8_t vector, IDTEntry *entry); - - /*! - * Enables or disables interrupts by changing the IF flag of the EFLAGS - * register. - * - * Equivalent to the `cli` and `sti` instructions. - */ - CPUOperationStatus SetInterruptsEnabled(bool enabled); - - /*! - * Sets the specified bits of the EFLAGS register. - */ - CPUOperationStatus SetFlags(uint32_t flagsBits); - - /*! - * Clears the specified bits of the EFLAGS register. - */ - CPUOperationStatus ClearFlags(uint32_t flagsBits); - - // ----- Instructions ----------------------------------------------------- - - /*! - * Pushes an immediate 32-bit value onto the stack. - * - * Equivalent to "push ". - */ - CPUOperationStatus Push(uint32_t value); - - /*! - * Pushes a CPU register onto the stack. - * - * Equivalent to "push ". - */ - CPUOperationStatus PushReg(enum CpuReg reg); - - /*! - * Pushes the CPU's flags onto the stack. - * - * Equivalent to "pushfd". - */ - CPUOperationStatus PushFlags(); - - /*! - * Pops an immediate 32-bit value from the stack. - * - * Equivalent to "pop", except the value is written to the specified variable. - */ - CPUOperationStatus Pop(uint32_t *value); - - /*! - * Pops a value from the stack into the specified CPU register. - * - * Equivalent to "pop ". - */ - CPUOperationStatus PopReg(enum CpuReg reg); - - /*! - * Pops the CPU's flags from the stack. - * - * Equivalent to "popfd". - */ - CPUOperationStatus PopFlags(); - - /*! - * Returns to the address at the top of the stack. - * - * Equivalent to "ret", or "pop eip" (if it was possible). - */ - CPUOperationStatus Ret(); - - // ----- Breakpoints ------------------------------------------------------ - - /*! - * Enables or disables software breakpoints. - * - * If the guest executes an INT 3h instruction while software breakpoints are enabled, - * the CPU emulator will stop and return CPU_EXIT_BREAKPOINT. The guest code will not - * have a chance to handle INT 3h while software breakpoints are enabled. - * - * This is an optional operation. TODO: implement capability checking. - */ - virtual CPUOperationStatus EnableSoftwareBreakpoints(bool enable); - - /*! - * Configures up to 4 hardware breakpoints. - * - * While these breakpoints are active, when the guest code triggers them, the CPU - * emulator will stop and return CPU_EXIT_BREAKPOINT. - * - * This is an optional operation. TODO: implement capability checking. - */ - virtual CPUOperationStatus SetHardwareBreakpoints(HardwareBreakpoints breakpoints); - - /*! - * Clears all hardware breakpoints. - * - * This is an optional operation. TODO: implement capability checking. - */ - virtual CPUOperationStatus ClearHardwareBreakpoints(); - - /*! - * Retrieves the address of the most recently hit breakpoint. Must be - * invoked after the CPU emulator stops due to a breakpoint, and before - * running the CPU again. - * - * Returns CPUS_OP_BREAKPOINT_NEVER_HIT if a breakpoint was not hit as of - * the most recent execution. - * - * This is an optional operation. TODO: implement capability checking. - */ - virtual CPUOperationStatus GetBreakpointAddress(uint32_t *address); - - // ----- Data ------------------------------------------------------------- - - /*! - * Retrieves information about why the CPU emulation exited. - */ - struct CpuExitInfo* GetExitInfo() { return &m_exitInfo; } -protected: - /*! - * The CPU exit information. - */ - struct CpuExitInfo m_exitInfo; - - /*! - * The I/O mapper that handles I/O and MMIO for the CPU. - */ - IOMapper *m_ioMapper; - - /*! - * Allows the implementation to do further initialization. - */ - virtual CPUInitStatus InitializeImpl() = 0; - - /*! - * Runs the CPU until interrupted. - */ - virtual CPUStatus RunImpl() = 0; - - /*! - * Runs one instruction on the CPU. - * - * This is an optional operation. TODO: implement capability checking. - */ - virtual CPUStatus StepImpl(); - - /*! - * Sends an interrupt to the CPU. - */ - virtual InterruptResult InterruptImpl(uint8_t vector) = 0; - - /*! - * Injects an interrupt into the VCPU. - */ - virtual CPUOperationStatus InjectInterrupt(uint8_t vector) = 0; - - /*! - * Determines if an interrupt can be injected into the VCPU. - */ - virtual bool CanInjectInterrupt() = 0; - - /*! - * Requests for an interrupt injection window. - */ - virtual void RequestInterruptWindow() = 0; - -private: - // TODO: use an AVL tree instead of a vector to speed up lookups - std::vector m_physMemMap; - - std::mutex m_interruptMutex; - std::mutex m_pendingInterruptsMutex; - std::queue m_pendingInterrupts; - uint8_t m_interruptHandlerCredits; - - void HandleInterruptQueue(); - void InjectPendingInterrupt(); -}; - -} -} diff --git a/src/cpu-module/vixen/cpu_module.h b/src/cpu-module/vixen/cpu_module.h deleted file mode 100644 index 7ce47c1..0000000 --- a/src/cpu-module/vixen/cpu_module.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include "vixen/module_common.h" -#include "vixen/cpu.h" - -// This file specifies the interface and exported data for a CPU module. -// Follow the instructions in cpu_module_def.h to declare a CPU module. - -namespace vixen { -namespace modules { -namespace cpu { - -using namespace vixen::cpu; - -// The CPU module API version -// Increment this if there are any ABI breaking changes or new features -const int apiVersion = 1; - - -// Base interface for CPU modules -class MODULE_API ICPUModule { -public: - virtual Cpu *GetCPU() = 0; - virtual void FreeCPU(Cpu *cpu) = 0; - virtual void Cleanup() = 0; -}; - - -// Function that retrieves an instance of the CPU module -MODULE_API typedef ICPUModule* (*CreateCPUModuleFunc)(); - - - -// CPU module information exported as vxnModuleInfo. -// This struct MUST remain backwards-compatible -- existing fields MUST NOT be -// modified, moved or removed. -struct Info { - vixen::modules::Info baseInfo; // This must ALWAYS be the first entry - APIVersion cpuModuleAPIVersion; - const char *className; - const char *moduleName; - const char *moduleVersion; - CreateCPUModuleFunc createModule; -}; - - - -// CPU module capabilities exported as vxnModuleCaps. -// This struct MUST remain backwards-compatible -- existing fields MUST NOT be -// modified, moved or removed. -struct Capabilities { - // Supports guest debugging operations such as single stepping and breakpoints - bool guestDebugging; -}; - -} -} -} - diff --git a/src/cpu-module/vixen/cpu_module_decl.h b/src/cpu-module/vixen/cpu_module_decl.h deleted file mode 100644 index b5042a8..0000000 --- a/src/cpu-module/vixen/cpu_module_decl.h +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once - -#include "vixen/cpu_module.h" - -// This file provides helper macros to declare a CPU module. -// -// How to declare a CPU module: -// - Include this file -// - Create a class that implements ICPUModule -// - At the top of the .cpp file, create the module definition block: -// CPU_MODULE_BEGIN -// CPU_MODULE_INFO(, "", "") -// CPU_MODULE_CAPS.().(); -// CPU_MODULE_END -// where: -// is the name of the class that implements ICPUModule; -// is the display name of the module; -// is the version of the module; and -// and are methods of the CapabilitiesBuilder struct. -// -// CPU_MODULE_INFO is required and must be specified exactly once. -// -// CPU_MODULE_CAPS is optional and may be specified at most once. -// Use method chaining to specify multiple capabilities. Invoking the same -// method twice has no additional effect. - - -namespace vixen { -namespace modules { -namespace cpu { - -#define CPU_MODULE_BEGIN extern "C" { -#define CPU_MODULE_END } - -// Declare the CPU module information -// - classType is the name of the class that implements ICPUModule -// - moduleName is the name of the module -// - moduleVersion is the version string of the module -#define CPU_MODULE_INFO(classType, moduleName, moduleVersion) \ - MODULE_EXPORT ICPUModule* getCPUModule() { \ - static classType singleton; \ - return &singleton; \ - } \ - MODULE_EXPORT Info vxnModuleInfo = { \ - COMMON_MODULE_INFO(TYPE_CPU), \ - apiVersion, \ - #classType, \ - moduleName, \ - moduleVersion, \ - getCPUModule, \ - }; - - -// Helper struct for building the CPU module capabilities -struct CapabilitiesBuilder { - Capabilities caps; - CapabilitiesBuilder& guestDebugging() { caps.guestDebugging = true; return *this; } - operator Capabilities() { return caps; } -}; - - -// Declare the CPU module capabilities -#define CPU_MODULE_CAPS \ - MODULE_EXPORT Capabilities vxnModuleCaps = CapabilitiesBuilder() - -} -} -} diff --git a/src/module-common/CMakeLists.txt b/src/module-common/CMakeLists.txt deleted file mode 100644 index be60a2f..0000000 --- a/src/module-common/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -# Add sources -file(GLOB DIR_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/vixen/*.h - ) - -file(GLOB DIR_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/vixen/*.cpp - ) - -set(SOURCES ${SOURCES} - ${DIR_HEADERS} - ${DIR_SOURCES} - ) - -# Add Visual Studio filters to better organize the code -vs_set_filters("${SOURCES}" "vixen") - -# Main Executable -if(NOT MSVC) - add_definitions("-Wall -Werror -O0 -g") -endif() -add_library(module-common STATIC "${SOURCES}") -target_include_directories(module-common PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - -# Include viXen common code -target_link_libraries(module-common common) - -# Make the Debug and RelWithDebInfo targets use Program Database for Edit and Continue for easier debugging -vs_use_edit_and_continue() - diff --git a/src/module-common/vixen/module_common.cpp b/src/module-common/vixen/module_common.cpp deleted file mode 100644 index f7efca5..0000000 --- a/src/module-common/vixen/module_common.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "vixen/module_common.h" - -// This file tells CMake we're building a C++ project. diff --git a/src/module-common/vixen/module_common.h b/src/module-common/vixen/module_common.h deleted file mode 100644 index b8c6b2f..0000000 --- a/src/module-common/vixen/module_common.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -namespace vixen { -namespace modules { - -// Shared library export/import specs -#ifdef _WIN32 - #if defined(MODULE_EXPORTS) - #define MODULE_API __declspec(dllexport) - #else - #define MODULE_API __declspec(dllimport) - #endif -#else - #define MODULE_API -#endif - - -#ifdef _WIN32 - #define MODULE_EXPORT __declspec(dllexport) -#else - #define MODULE_EXPORT -#endif - - -// Module types -enum Type { - TYPE_CPU, -}; - -// The API version type -typedef unsigned long APIVersion; - -// The common module API version -// Increment this if there are any ABI breaking changes -const APIVersion apiVersion = 1; - -// Base module information exposed to the emulator core. -// This struct MUST remain backwards-compatible -- existing fields MUST NOT be -// modified, moved or removed. -struct Info { - APIVersion apiVersion; - Type type; -}; - -// Field values for the above struct. -// Every derived module struct must define these values -#define COMMON_MODULE_INFO(type) {\ - apiVersion, \ - type \ -} - -} -}