├── bios ├── .gitignore ├── seabios.bin ├── vgabios.bin ├── bochs-bios.bin ├── bochs-vgabios.bin ├── seabios-debug.bin ├── vgabios-debug.bin └── fetch-and-build-seabios.sh ├── docs ├── .gitignore ├── profiling.md ├── filesystem.md ├── linux-9p-image.md └── cpu-idling.md ├── .cargo └── config ├── tests ├── expect │ ├── tests │ │ ├── inc.asm │ │ ├── pop.asm │ │ ├── push.asm │ │ ├── add.asm │ │ ├── task_switch_test.asm │ │ ├── indirect-call.asm │ │ ├── mem32r.asm │ │ ├── mem32w.asm │ │ ├── mov-immoffs.asm │ │ ├── loop.asm │ │ ├── mem32rmw.asm │ │ ├── task_switch_test_sse.asm │ │ ├── call-ret.asm │ │ ├── do-while.asm │ │ ├── if.asm │ │ ├── while-do.asm │ │ ├── sti.asm │ │ └── Makefile │ └── readme.md ├── nasm │ ├── footer.inc │ ├── fdecstp.asm │ ├── fincstp.asm │ ├── fchs.asm │ ├── fsqrt.asm │ ├── mov_sreg_ud1.asm │ ├── mov_sreg_ud2.asm │ ├── fdiv.asm │ ├── fdivr.asm │ ├── fyl2x.asm │ ├── fscale.asm │ ├── fyl2xp1.asm │ ├── cmp16-setbe.asm │ ├── idiv8-overflow.asm │ ├── leave32.asm │ ├── fptan.asm │ ├── fstsw.asm │ ├── Readme.md │ ├── cmpxchg-setbe.asm │ ├── idiv16-overflow.asm │ ├── leave16.asm │ ├── fxtract-zero.asm │ ├── fxtract.asm │ ├── idiv32-overflow.asm │ ├── indirect-jump.asm │ ├── fpu_m80.asm │ ├── pushf.asm │ ├── pop_esp2.asm │ ├── pop_esp.asm │ ├── fdiv-zero.asm │ ├── f2xm1.asm │ ├── frndint.asm │ ├── fyl2x-zero.asm │ ├── fstm80.asm │ ├── fsincos.asm │ ├── ret-imm.asm │ ├── fprem.asm │ ├── shufps-edgecase.asm │ ├── fprem1.asm │ ├── emms.asm │ ├── indirect-call.asm │ ├── loop.asm │ ├── paddw.asm │ ├── arith-optimisations.asm │ ├── fsave_frstor.asm │ ├── fstenv.asm │ ├── movq.asm │ ├── lea-nop.asm │ ├── cmpxchg8b.asm │ ├── movaps.asm │ ├── movntpd.asm │ ├── movntps.asm │ ├── jcxz.asm │ ├── loopnz.asm │ ├── loopz.asm │ ├── movd.asm │ ├── pshufw.asm │ ├── cvtpi2ps.asm │ ├── por.asm │ ├── pandn.asm │ ├── paddsb.asm │ ├── paddsw.asm │ ├── paddusb.asm │ ├── paddusw.asm │ ├── pcmpeqd.asm │ ├── pcmpeqw.asm │ ├── pcmpgtw.asm │ ├── pmulhw.asm │ ├── pmullw.asm │ ├── psubsb.asm │ ├── psubsw.asm │ ├── psubusb.asm │ ├── psubusw.asm │ ├── packssdw.asm │ ├── pcmpgtd.asm │ ├── packsswb.asm │ ├── cmpxchg.asm │ ├── punpckhbw.asm │ ├── punpckhdq.asm │ ├── punpckhwd.asm │ ├── cvttps2pi.asm │ ├── paddb.asm │ ├── paddd.asm │ ├── psubb.asm │ ├── psubd.asm │ ├── pand.asm │ ├── pmaddwd.asm │ ├── bts-reg16.asm │ ├── btr-reg16.asm │ ├── bts-reg32.asm │ ├── btr-reg32.asm │ ├── pcmpeqb.asm │ ├── mov_sreg.asm │ ├── btc-reg16.asm │ ├── psubw.asm │ ├── btc-reg32.asm │ ├── bts-imm.asm │ ├── psrad.asm │ ├── maskmovq.asm │ ├── btr-imm.asm │ ├── psraw.asm │ ├── psrld.asm │ ├── pmuludq.asm │ ├── push.asm │ ├── pcmpgtb.asm │ ├── pxor.asm │ ├── btc-imm.asm │ ├── pslld.asm │ ├── punpckldq.asm │ ├── punpcklwd.asm │ ├── psrlw.asm │ ├── packuswb.asm │ ├── punpcklbw.asm │ ├── cvtps2pi.asm │ ├── maskmovdqu.asm │ ├── psllq.asm │ ├── header.inc │ ├── mov16.asm │ ├── psllw.asm │ ├── jump.asm │ ├── psrlq.asm │ ├── comiss.asm │ └── ucomiss.asm ├── kvm-unit-tests │ ├── x86 │ │ ├── Makefile │ │ ├── ioram.h │ │ ├── port80.c │ │ ├── realmode.lds │ │ ├── setjmp.c │ │ ├── types.h │ │ ├── flat.lds │ │ ├── smptest.c │ │ ├── cmpxchg8b.c │ │ ├── Makefile.x86_64 │ │ ├── Makefile.i386 │ │ ├── taskswitch.c │ │ ├── tsc.c │ │ ├── idt_test.c │ │ ├── sieve.c │ │ ├── kvmclock.h │ │ ├── rmap_chain.c │ │ ├── tsc_adjust.c │ │ └── hyperv.c │ ├── lib │ │ ├── auxinfo.c │ │ ├── x86 │ │ │ ├── asm │ │ │ │ ├── spinlock.h │ │ │ │ ├── stack.h │ │ │ │ ├── bitops.h │ │ │ │ ├── barrier.h │ │ │ │ ├── page.h │ │ │ │ ├── pci.h │ │ │ │ └── io.h │ │ │ ├── isr.h │ │ │ ├── fake-apic.h │ │ │ ├── smp.h │ │ │ ├── setjmp64.S │ │ │ ├── setjmp32.S │ │ │ ├── stack.c │ │ │ ├── atomic.c │ │ │ ├── fwcfg.c │ │ │ ├── setup.c │ │ │ ├── apic.h │ │ │ ├── acpi.c │ │ │ ├── fwcfg.h │ │ │ └── vm.h │ │ ├── asm-generic │ │ │ ├── pci.h │ │ │ ├── spinlock.h │ │ │ ├── barrier.h │ │ │ ├── page.h │ │ │ ├── pci-host-bridge.h │ │ │ └── atomic.h │ │ ├── libfdt │ │ │ ├── README │ │ │ ├── Makefile.libfdt │ │ │ └── version.lds │ │ ├── kbuild.h │ │ ├── auxinfo.h │ │ ├── argv.h │ │ ├── util.c │ │ ├── chr-testdev.h │ │ ├── setjmp.h │ │ ├── abort.c │ │ ├── stack.h │ │ ├── linux │ │ │ └── const.h │ │ ├── util.h │ │ ├── string.h │ │ ├── errata.h │ │ ├── bitops.h │ │ ├── pci-host-generic.h │ │ ├── chr-testdev.c │ │ └── pci-edu.c │ ├── .gitignore │ ├── api │ │ ├── exception.hh │ │ ├── api-sample.cc │ │ ├── exception.cc │ │ ├── memmap.hh │ │ └── identity.hh │ ├── COPYRIGHT │ └── run.js ├── devices │ ├── testfs │ │ ├── 7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730 │ │ └── 5d70f436aa013f4f1d5af4a5e8149b479c813ab4ceea0bcf8b01f78eac84fd25 │ └── testfs.json ├── jit-paging │ ├── Makefile │ └── README.md ├── qemu │ ├── Readme.md │ ├── Makefile │ ├── LICENSE │ └── test-i386-code16.S ├── api │ ├── test.js │ ├── clean-shutdown.js │ ├── floppy-insert-eject.js │ ├── reset.js │ └── serial.js ├── rust │ └── verify-wasmgen-dummy-output.js ├── manual │ └── gc.html ├── Readme.md └── benchmark │ └── arch-python.js ├── src ├── rust │ ├── wasmgen │ │ └── mod.rs │ ├── cpu │ │ ├── call_indirect.rs │ │ └── mod.rs │ ├── config.rs │ ├── gen │ │ └── mod.rs │ ├── js_api.rs │ ├── page.rs │ ├── lib.rs │ ├── prefix.rs │ ├── paging.rs │ ├── regs.rs │ ├── state_flags.rs │ └── leb.rs ├── externs.js ├── config.js └── browser │ └── worker_bus.js ├── tools ├── docker │ ├── debian │ │ ├── getty-noclear.conf │ │ ├── getty-override.conf │ │ ├── getty-autologin-serial.conf │ │ ├── networking.sh │ │ ├── boot-9p │ │ ├── build-container.sh │ │ ├── Readme.md │ │ ├── logind.conf │ │ └── xorg.conf │ ├── exec │ │ ├── build.sh │ │ └── Dockerfile │ ├── README.md │ └── test-image │ │ └── Dockerfile └── rust-lld-wrapper ├── .gitattributes ├── .editorconfig ├── .rustfmt.toml ├── .vscode └── tasks.json ├── .gitignore ├── Cargo.toml ├── .jshint.json ├── .devcontainer ├── Dockerfile └── devcontainer.json ├── examples ├── worker.js ├── worker.html ├── debian.html ├── destroy.html ├── basic.html ├── nodejs.js ├── async_load.html └── nodejs_state.js ├── gen └── util.js ├── LICENSE └── lib └── utf8.js /bios/.gitignore: -------------------------------------------------------------------------------- 1 | *.gz 2 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | target-dir = "build" 3 | -------------------------------------------------------------------------------- /tests/expect/tests/inc.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | inc eax 3 | hlt 4 | -------------------------------------------------------------------------------- /tests/expect/tests/pop.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | pop eax 3 | hlt 4 | -------------------------------------------------------------------------------- /tests/expect/tests/push.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | push eax 3 | hlt 4 | -------------------------------------------------------------------------------- /src/rust/wasmgen/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod wasm_builder; 2 | mod wasm_opcodes; 3 | -------------------------------------------------------------------------------- /tests/expect/tests/add.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | add ebx, eax 3 | hlt 4 | -------------------------------------------------------------------------------- /bios/seabios.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2Cmo/v86/master/bios/seabios.bin -------------------------------------------------------------------------------- /bios/vgabios.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2Cmo/v86/master/bios/vgabios.bin -------------------------------------------------------------------------------- /tests/expect/tests/task_switch_test.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | fadd 3 | hlt 4 | -------------------------------------------------------------------------------- /tests/nasm/footer.inc: -------------------------------------------------------------------------------- 1 | 2 | loop: 3 | hlt 4 | jmp loop 5 | -------------------------------------------------------------------------------- /tools/docker/debian/getty-noclear.conf: -------------------------------------------------------------------------------- 1 | [Service] 2 | TTYVTDisallocate=no 3 | -------------------------------------------------------------------------------- /tests/expect/tests/indirect-call.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | call [eax] 3 | hlt 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | lib/zstd/* linguist-vendored 2 | lib/softfloat/* linguist-vendored 3 | -------------------------------------------------------------------------------- /bios/bochs-bios.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2Cmo/v86/master/bios/bochs-bios.bin -------------------------------------------------------------------------------- /tests/expect/tests/mem32r.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | mov eax, [ebx + 123456789] 3 | hlt 4 | -------------------------------------------------------------------------------- /tests/expect/tests/mem32w.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | mov [ebx + 123456789], eax 3 | hlt 4 | -------------------------------------------------------------------------------- /tests/expect/tests/mov-immoffs.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | mov eax, [0xcafe] 3 | hlt 4 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/Makefile: -------------------------------------------------------------------------------- 1 | include $(SRCDIR)/$(TEST_DIR)/Makefile.$(ARCH) 2 | -------------------------------------------------------------------------------- /bios/bochs-vgabios.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2Cmo/v86/master/bios/bochs-vgabios.bin -------------------------------------------------------------------------------- /bios/seabios-debug.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2Cmo/v86/master/bios/seabios-debug.bin -------------------------------------------------------------------------------- /bios/vgabios-debug.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2Cmo/v86/master/bios/vgabios-debug.bin -------------------------------------------------------------------------------- /tests/devices/testfs/7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730: -------------------------------------------------------------------------------- 1 | bar 2 | -------------------------------------------------------------------------------- /tests/expect/tests/loop.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | 3 | start: 4 | loop start 5 | hlt 6 | 7 | -------------------------------------------------------------------------------- /tests/expect/tests/mem32rmw.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | inc dword [eax + 123456789] 3 | hlt 4 | -------------------------------------------------------------------------------- /tests/expect/tests/task_switch_test_sse.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | andpd xmm0, xmm1 3 | hlt 4 | -------------------------------------------------------------------------------- /tests/devices/testfs/5d70f436aa013f4f1d5af4a5e8149b479c813ab4ceea0bcf8b01f78eac84fd25: -------------------------------------------------------------------------------- 1 | foobaz 2 | -------------------------------------------------------------------------------- /src/rust/cpu/call_indirect.rs: -------------------------------------------------------------------------------- 1 | #[no_mangle] 2 | pub fn call_indirect1(f: fn(u16), x: u16) { f(x); } 3 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/auxinfo.c: -------------------------------------------------------------------------------- 1 | #include "auxinfo.h" 2 | struct auxinfo auxinfo = { PROGNAME }; 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root=true 2 | 3 | [*.js] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 4 7 | -------------------------------------------------------------------------------- /tests/expect/tests/call-ret.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | call test 3 | hlt 4 | 5 | test: 6 | inc eax 7 | ret 8 | -------------------------------------------------------------------------------- /src/rust/config.rs: -------------------------------------------------------------------------------- 1 | pub const LOG_PAGE_FAULTS: bool = false; 2 | 3 | pub const VMWARE_HYPERVISOR_PORT: bool = true; 4 | -------------------------------------------------------------------------------- /tests/nasm/fdecstp.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | fdecstp 6 | 7 | %include "footer.inc" 8 | -------------------------------------------------------------------------------- /tests/nasm/fincstp.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | fincstp 6 | 7 | %include "footer.inc" 8 | -------------------------------------------------------------------------------- /tests/expect/tests/do-while.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | 3 | start: 4 | inc ebx 5 | cmp eax, 10 6 | jnz start 7 | 8 | hlt 9 | -------------------------------------------------------------------------------- /tests/expect/tests/if.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | cmp eax, 5 3 | jg else 4 | inc ecx 5 | 6 | else: 7 | inc ebx 8 | hlt 9 | -------------------------------------------------------------------------------- /tests/nasm/fchs.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | fldz 6 | fchs 7 | 8 | %include "footer.inc" 9 | -------------------------------------------------------------------------------- /tests/nasm/fsqrt.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | fldpi 6 | fsqrt 7 | 8 | %include "footer.inc" 9 | -------------------------------------------------------------------------------- /tests/nasm/mov_sreg_ud1.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | db 8eh 6 | db 3fh 7 | 8 | %include "footer.inc" 9 | -------------------------------------------------------------------------------- /tests/nasm/mov_sreg_ud2.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | db 8ch 6 | db 3fh 7 | 8 | %include "footer.inc" 9 | -------------------------------------------------------------------------------- /tools/docker/debian/getty-override.conf: -------------------------------------------------------------------------------- 1 | [Service] 2 | ExecStart= 3 | ExecStart=-/sbin/agetty --autologin root --noissue --noclear %I 38400 $TERM 4 | -------------------------------------------------------------------------------- /tests/nasm/fdiv.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | fldz 6 | fldz 7 | fdiv 8 | 9 | %include "footer.inc" 10 | -------------------------------------------------------------------------------- /tests/nasm/fdivr.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | fldz 6 | fldz 7 | fdivr 8 | 9 | %include "footer.inc" 10 | -------------------------------------------------------------------------------- /tests/nasm/fyl2x.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | fld1 6 | fldpi 7 | fyl2x 8 | 9 | %include "footer.inc" 10 | -------------------------------------------------------------------------------- /src/rust/gen/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod interpreter; 2 | pub mod interpreter0f; 3 | 4 | pub mod jit; 5 | pub mod jit0f; 6 | 7 | pub mod analyzer; 8 | pub mod analyzer0f; 9 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/asm/spinlock.h: -------------------------------------------------------------------------------- 1 | #ifndef __ASM_SPINLOCK_H 2 | #define __ASM_SPINLOCK_H 3 | 4 | #include 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /tests/nasm/fscale.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | fldpi 6 | fldpi 7 | fscale 8 | 9 | %include "footer.inc" 10 | -------------------------------------------------------------------------------- /tests/nasm/fyl2xp1.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | fld1 6 | fldpi 7 | fyl2xp1 8 | 9 | %include "footer.inc" 10 | -------------------------------------------------------------------------------- /tests/expect/tests/while-do.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | 3 | start: 4 | cmp eax, 10 5 | jz end 6 | add ebx, 1 7 | jmp start 8 | 9 | end: 10 | hlt 11 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/asm-generic/pci.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASM_GENERIC_PCI_H_ 2 | #define _ASM_GENERIC_PCI_H_ 3 | #error need architecture specific asm/pci.h 4 | #endif 5 | -------------------------------------------------------------------------------- /tools/docker/debian/getty-autologin-serial.conf: -------------------------------------------------------------------------------- 1 | [Service] 2 | ExecStart= 3 | ExecStart=-/sbin/agetty --autologin root --noissue --noclear -s %I 115200,38400,9600 vt102 4 | -------------------------------------------------------------------------------- /tests/expect/tests/sti.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | sti 3 | mov eax, 42424242 4 | ; handle_irqs check should be inserted here 5 | mov eax, 53535353 6 | 7 | hlt 8 | 9 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/ioram.h: -------------------------------------------------------------------------------- 1 | #ifndef __IO_RAM_H 2 | #define __IO_RAM_H 3 | 4 | #define IORAM_BASE_PHYS 0xff000000UL 5 | #define IORAM_LEN 0x10000UL 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /tests/nasm/cmp16-setbe.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov ax, -1 6 | cmp ax, -3 7 | setbe bl 8 | 9 | %include "footer.inc" 10 | -------------------------------------------------------------------------------- /tests/nasm/idiv8-overflow.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov ax, 8000h 6 | mov bl, -1 7 | idiv bl 8 | 9 | %include "footer.inc" 10 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/libfdt/README: -------------------------------------------------------------------------------- 1 | 2 | The code in this directory is originally imported from the libfdt 3 | directory of git://git.jdl.com/software/dtc.git - version 1.4.0. 4 | 5 | -------------------------------------------------------------------------------- /tests/nasm/leave32.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | lea ebp, [esp+10h] 6 | mov dword [ebp], 123456789 7 | leave 8 | 9 | %include "footer.inc" 10 | -------------------------------------------------------------------------------- /tests/nasm/fptan.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | fldpi 6 | fptan 7 | 8 | fldpi 9 | fldpi 10 | fpatan 11 | 12 | %include "footer.inc" 13 | -------------------------------------------------------------------------------- /tests/nasm/fstsw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov eax, 12345678h 6 | fstsw ax 7 | push 87654321h 8 | fstsw [esp] 9 | 10 | %include "footer.inc" 11 | -------------------------------------------------------------------------------- /tests/nasm/Readme.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | The tests in this folder are not comprehensive by any means at the 4 | moment. 5 | 6 | # Automated Testing 7 | 8 | - Run `make nasmtests` in the root of the project 9 | -------------------------------------------------------------------------------- /tests/nasm/cmpxchg-setbe.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov eax, 1 6 | mov edx, 2 7 | cmpxchg eax, edx 8 | setbe cl 9 | 10 | %include "footer.inc" 11 | -------------------------------------------------------------------------------- /tests/nasm/idiv16-overflow.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov ax, 0000h 6 | mov dx, 8000h 7 | mov bx, -1 8 | idiv bx 9 | 10 | %include "footer.inc" 11 | -------------------------------------------------------------------------------- /tests/nasm/leave16.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | lea ebp, [esp+10h] 6 | mov dword [ebp], 123456789 7 | db 0x66 8 | leave 9 | 10 | %include "footer.inc" 11 | -------------------------------------------------------------------------------- /tests/nasm/fxtract-zero.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | 6 | %include "header.inc" 7 | 8 | push 0 9 | fild dword [esp] 10 | fxtract 11 | 12 | %include "footer.inc" 13 | -------------------------------------------------------------------------------- /tests/nasm/fxtract.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | 6 | %include "header.inc" 7 | 8 | push 12345 9 | fild dword [esp] 10 | fxtract 11 | 12 | %include "footer.inc" 13 | -------------------------------------------------------------------------------- /tests/nasm/idiv32-overflow.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov eax, 00000000h 6 | mov edx, 80000000h 7 | mov ebx, -1 8 | idiv ebx 9 | 10 | %include "footer.inc" 11 | -------------------------------------------------------------------------------- /tests/nasm/indirect-jump.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | 5 | %include "header.inc" 6 | 7 | mov eax, foo 8 | jmp eax 9 | foo: 10 | xor eax, eax 11 | 12 | %include "footer.inc" 13 | -------------------------------------------------------------------------------- /tools/docker/debian/networking.sh: -------------------------------------------------------------------------------- 1 | rmmod ne2k-pci && modprobe ne2k-pci 2 | ifconfig enp0s5 192.168.1.5 netmask 255.255.255.0 up 3 | route add default gw 192.168.1.1 4 | echo "nameserver 8.8.8.8" > /etc/resolv.conf 5 | -------------------------------------------------------------------------------- /src/rust/js_api.rs: -------------------------------------------------------------------------------- 1 | use cpu::cpu::translate_address_system_read; 2 | 3 | #[no_mangle] 4 | pub unsafe fn translate_address_system_read_js(addr: i32) -> u32 { 5 | translate_address_system_read(addr).unwrap() 6 | } 7 | -------------------------------------------------------------------------------- /tests/nasm/fpu_m80.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | 6 | %include "header.inc" 7 | 8 | push 1 9 | push 0 10 | push 0 11 | fld tword [esp-8] 12 | 13 | %include "footer.inc" 14 | -------------------------------------------------------------------------------- /tests/nasm/pushf.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | pushf 6 | and dword [esp], ~0x0200 ; if 7 | 8 | db 66h 9 | pushf 10 | and dword [esp], ~0x0200 11 | 12 | %include "footer.inc" 13 | -------------------------------------------------------------------------------- /tests/nasm/pop_esp2.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | 6 | %include "header.inc" 7 | 8 | ; pop esp encoded using 8F 9 | mov esp, stack_top-16 10 | db 8Fh, 0C4h 11 | 12 | %include "footer.inc" 13 | -------------------------------------------------------------------------------- /tests/nasm/pop_esp.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | 6 | %include "header.inc" 7 | 8 | mov esp, stack_top-16 9 | mov dword [esp], 55aaaa55h 10 | pop dword [esp-12] 11 | 12 | %include "footer.inc" 13 | -------------------------------------------------------------------------------- /tests/nasm/fdiv-zero.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | 6 | %include "header.inc" 7 | 8 | push 1234 9 | fild dword [esp] 10 | push 0 11 | fild dword [esp] 12 | fdiv 13 | 14 | %include "footer.inc" 15 | -------------------------------------------------------------------------------- /tests/nasm/f2xm1.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | fldz 6 | f2xm1 7 | 8 | fld1 9 | f2xm1 10 | 11 | fld1 12 | fchs 13 | f2xm1 14 | 15 | fldln2 16 | f2xm1 17 | 18 | %include "footer.inc" 19 | -------------------------------------------------------------------------------- /tests/nasm/frndint.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | fldz 6 | frndint 7 | 8 | fldpi 9 | frndint 10 | 11 | fldl2t 12 | frndint 13 | 14 | fldln2 15 | frndint 16 | 17 | %include "footer.inc" 18 | -------------------------------------------------------------------------------- /tests/nasm/fyl2x-zero.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | 6 | %include "header.inc" 7 | 8 | push 1234 9 | fild dword [esp] 10 | push 0 11 | fild dword [esp] 12 | fyl2x 13 | 14 | %include "footer.inc" 15 | -------------------------------------------------------------------------------- /tools/docker/exec/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | cd "$(dirname "$0")" 4 | tar -cf - ../../../{*.html,*.js,*.css,gen,lib,src,bios,.cargo,Cargo.toml,Makefile,tools} | \ 5 | docker build -t v86:alpine-3.14 -f tools/docker/exec/Dockerfile - 6 | -------------------------------------------------------------------------------- /tests/jit-paging/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CC_I386=$(CC) -m32 3 | CFLAGS=-Wall -g -fno-strict-aliasing -fPIC -static 4 | LDFLAGS= 5 | 6 | 7 | test-jit: test-jit.c 8 | $(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $(. Just use . 6 | #endif 7 | 8 | #define HAVE_ARCH_BACKTRACE_FRAME 9 | #define HAVE_ARCH_BACKTRACE 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /tests/nasm/fprem1.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | fld1 6 | fldz 7 | fprem1 8 | 9 | fld1 10 | fldpi 11 | fprem1 12 | 13 | fld1 14 | fldl2t 15 | fprem1 16 | 17 | fldz 18 | fldz 19 | fprem1 20 | 21 | %include "footer.inc" 22 | -------------------------------------------------------------------------------- /tests/devices/testfs.json: -------------------------------------------------------------------------------- 1 | {"fsroot":[["foo",4,1531432001,33188,1000,1000,"7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730"],["dir",4096,1532940393,16877,1000,1000,[["bar",7,1532940393,33188,1000,1000,"5d70f436aa013f4f1d5af4a5e8149b479c813ab4ceea0bcf8b01f78eac84fd25"]]]],"version":3,"size":4107} 2 | -------------------------------------------------------------------------------- /tests/nasm/emms.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | myquad: 6 | dq 0xad0000ceadad00ff 7 | mydword: 8 | dd 0xcafebabe 9 | myaddress: 10 | dq 0x00adbeefc0de00ce 11 | 12 | %include "header.inc" 13 | 14 | emms 15 | ; TODO: Check tag word 16 | 17 | %include "footer.inc" 18 | -------------------------------------------------------------------------------- /tests/qemu/Readme.md: -------------------------------------------------------------------------------- 1 | How to run: 2 | 3 | - Obtain the `linux3.iso` image (see [Readme.md](../../Readme.md)) 4 | - Run `make test-i386` 5 | - Get the result on the host: `./test-386 > reference` 6 | - Get the result from the VM: `./run.js > result` 7 | - The difference should be empty: `diff reference result` 8 | -------------------------------------------------------------------------------- /tests/nasm/indirect-call.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | 5 | %include "header.inc" 6 | 7 | mov eax, foo 8 | call eax 9 | foo: 10 | xor eax, eax 11 | ; clear stack (pushed eip is not the same between vm and gdb execution) 12 | mov dword [esp], 0 13 | 14 | %include "footer.inc" 15 | -------------------------------------------------------------------------------- /tests/nasm/loop.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov ecx, 0x10042 6 | mov eax, 0 7 | start1: 8 | inc eax 9 | loop start1 10 | 11 | mov ecx, 0x10005 12 | mov ebx, 0 13 | start2: 14 | inc ebx 15 | db 67h 16 | loop start2 17 | 18 | %include "footer.inc" 19 | -------------------------------------------------------------------------------- /tests/nasm/paddw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | myquad: 6 | dq 0xad0000ceadad00ff 7 | mydword: 8 | dd 0xcafebabe 9 | myaddress: 10 | dq 0x00adbeefc0de00ce 11 | 12 | %include "header.inc" 13 | 14 | movq mm0, [myquad] 15 | paddw mm0, [myaddress] 16 | 17 | %include "footer.inc" 18 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/asm/bitops.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASMX86_BITOPS_H_ 2 | #define _ASMX86_BITOPS_H_ 3 | 4 | #ifndef _BITOPS_H_ 5 | #error only can be included directly 6 | #endif 7 | 8 | #ifdef __x86_64__ 9 | #define BITS_PER_LONG 64 10 | #else 11 | #define BITS_PER_LONG 32 12 | #endif 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/rust/cpu/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod arith; 2 | pub mod call_indirect; 3 | pub mod cpu; 4 | pub mod fpu; 5 | pub mod global_pointers; 6 | pub mod instructions; 7 | pub mod instructions_0f; 8 | pub mod memory; 9 | pub mod misc_instr; 10 | pub mod modrm; 11 | pub mod pic; 12 | pub mod sse_instr; 13 | pub mod string; 14 | pub mod vga; 15 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/.gitignore: -------------------------------------------------------------------------------- 1 | .gdbinit 2 | *.a 3 | *.d 4 | *.o 5 | *.flat 6 | *.elf 7 | .pc 8 | patches 9 | .stgit-* 10 | cscope.* 11 | *.swp 12 | /lib/asm 13 | /config.mak 14 | /*-run 15 | /msr.out 16 | /tests 17 | /build-head 18 | /logs/ 19 | /logs.old/ 20 | /api/api-sample 21 | /api/dirty-log 22 | /api/dirty-log-perf 23 | -------------------------------------------------------------------------------- /tests/nasm/arith-optimisations.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | xor eax, eax 6 | pushf 7 | and dword [esp], 8ffh 8 | 9 | test ebx, ebx 10 | pushf 11 | and dword [esp], 8ffh 12 | 13 | cmp ecx, 0 14 | pushf 15 | and dword [esp], 8ffh 16 | 17 | %include "footer.inc" 18 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/kbuild.h: -------------------------------------------------------------------------------- 1 | #ifndef _KBUILD_H_ 2 | #define _KBUILD_H_ 3 | #define DEFINE(sym, val) \ 4 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) 5 | #define OFFSET(sym, str, mem) DEFINE(sym, offsetof(struct str, mem)) 6 | #define COMMENT(x) asm volatile("\n->#" x) 7 | #define BLANK() asm volatile("\n->" : : ) 8 | #endif 9 | -------------------------------------------------------------------------------- /tests/nasm/fsave_frstor.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | sub esp, 128 6 | fldz 7 | fld1 8 | fsave [esp] 9 | frstor [esp] 10 | mov dword [esp + 12], 0 ; fpu eip (currently not emulated) 11 | mov dword [esp + 16], 0 ; fpu cs/opcode (currently not emulated) 12 | 13 | %include "footer.inc" 14 | -------------------------------------------------------------------------------- /tests/nasm/fstenv.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | 6 | %include "header.inc" 7 | 8 | fstenv [esp] 9 | 10 | ; zero undefined fields 11 | mov word [esp + 0 + 2], 0 12 | mov word [esp + 4 + 2], 0 13 | mov word [esp + 8 + 2], 0 14 | mov word [esp + 24 + 2], 0 15 | 16 | %include "footer.inc" 17 | -------------------------------------------------------------------------------- /tests/nasm/movq.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | myquad: 6 | dq 0x1234567890abcdef 7 | mydword: 8 | dd 0xcafebabe 9 | myaddress: 10 | dd 0xdeadbeef 11 | 12 | %include "header.inc" 13 | 14 | movq mm0, [myquad] 15 | movq [myaddress], mm0 16 | movq mm1, [myaddress] 17 | movq mm4, mm0 18 | 19 | %include "footer.inc" 20 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/setjmp.c: -------------------------------------------------------------------------------- 1 | #include "libcflat.h" 2 | #include "setjmp.h" 3 | 4 | int main() 5 | { 6 | volatile int i; 7 | jmp_buf j; 8 | 9 | if (setjmp(j) == 0) { 10 | i = 0; 11 | } 12 | printf("%d\n", i); 13 | if (++i < 10) { 14 | longjmp(j, 1); 15 | } 16 | 17 | printf("done\n"); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/isr.h: -------------------------------------------------------------------------------- 1 | #ifndef __ISR_TEST__ 2 | #define __ISR_TEST__ 3 | 4 | typedef struct { 5 | ulong regs[sizeof(ulong)*2]; 6 | ulong func; 7 | ulong rip; 8 | ulong cs; 9 | ulong rflags; 10 | } isr_regs_t; 11 | 12 | void handle_irq(unsigned vec, void (*func)(isr_regs_t *regs)); 13 | void handle_external_interrupt(int vector); 14 | #endif 15 | -------------------------------------------------------------------------------- /tests/expect/tests/Makefile: -------------------------------------------------------------------------------- 1 | build_dir := build 2 | source_files := $(wildcard *.asm) 3 | executable_files := $(patsubst %.asm,$(build_dir)/%.bin,$(source_files)) 4 | 5 | .PHONY: all 6 | all: $(build_dir) $(executable_files) 7 | 8 | $(build_dir): 9 | mkdir -p $@ 10 | 11 | $(build_dir)/%.bin: %.asm 12 | nasm $< -o $@ 13 | 14 | .PHONY: clean 15 | clean: 16 | rm $(build_dir)/* 17 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/auxinfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This code is free software; you can redistribute it and/or modify it 3 | * under the terms of the GNU Library General Public License version 2. 4 | */ 5 | #ifndef _AUXINFO_H_ 6 | #define _AUXINFO_H_ 7 | struct auxinfo { 8 | const char *progname; 9 | }; 10 | 11 | /* No extern! Define a common symbol. */ 12 | struct auxinfo auxinfo; 13 | #endif 14 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/fake-apic.h: -------------------------------------------------------------------------------- 1 | #ifndef SILLY_APIC_H 2 | #define SILLY_APIC_H 3 | 4 | #define APIC_BASE 0x1000 5 | #define APIC_SIZE 0x100 6 | 7 | #define APIC_REG_NCPU 0x00 8 | #define APIC_REG_ID 0x04 9 | #define APIC_REG_SIPI_ADDR 0x08 10 | #define APIC_REG_SEND_SIPI 0x0c 11 | #define APIC_REG_IPI_VECTOR 0x10 12 | #define APIC_REG_SEND_IPI 0x14 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /tools/docker/README.md: -------------------------------------------------------------------------------- 1 | # Dockerfiles 2 | 3 | This directory contains Dockerfile to generate images for various purposes. 4 | 5 | ## debian 6 | 7 | To create a Docker image to run Debian inside v86. 8 | 9 | ## exec 10 | 11 | To create a Docker image to build and host v86 system and expose in a port (default 8000). 12 | 13 | ## test-image 14 | 15 | To create a Docker image that runs v86 tests. 16 | -------------------------------------------------------------------------------- /tests/nasm/lea-nop.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | ; nops 6 | lea edx, [edx] 7 | db 8Dh, 40h, 00h 8 | db 8Dh, 0B6h, 00h, 00h, 00h, 00h 9 | db 8Dh, 0BCh, 27h, 00h, 00h, 00h, 00h 10 | 11 | ; non-nops, but similar encodings 12 | lea eax, [bx+si] 13 | lea cx, [bx+di] 14 | lea edx, [edx+42] 15 | lea ebp, [ebp*2] 16 | 17 | %include "footer.inc" 18 | -------------------------------------------------------------------------------- /tests/nasm/cmpxchg8b.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | 5 | %include "header.inc" 6 | 7 | mov eax, 123456789 8 | mov edx, 987654321 9 | 10 | mov dword [esp], 123456789 11 | mov dword [esp+4], 987654321 12 | 13 | cmpxchg8b [esp] 14 | push eax 15 | push ecx 16 | push ebx 17 | push edx 18 | pushf 19 | and dword [esp], 8ffh 20 | 21 | %include "footer.inc" 22 | -------------------------------------------------------------------------------- /tests/nasm/movaps.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | myfloat0: 6 | dd 1.234567e20 7 | myfloat1: 8 | dd 2.345678e20 9 | myfloat2: 10 | dd 3.456789e20 11 | myfloat3: 12 | dd 4.567891e20 13 | myaddress: 14 | dd 0xdeadbeef 15 | %include "header.inc" 16 | 17 | movaps xmm0, [myfloat0] 18 | movaps [myaddress], xmm0 19 | movaps xmm1, [myaddress] 20 | 21 | %include "footer.inc" 22 | -------------------------------------------------------------------------------- /tests/nasm/movntpd.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | myfloat0: 6 | dd 1.234567e20 7 | myfloat1: 8 | dd 2.345678e20 9 | myfloat2: 10 | dd 3.456789e20 11 | myfloat3: 12 | dd 4.567891e20 13 | myaddress: 14 | dd 0xdeadbeef 15 | %include "header.inc" 16 | 17 | movapd xmm0, [myfloat0] 18 | movntpd [myaddress], xmm0 19 | movapd xmm1, [myaddress] 20 | 21 | %include "footer.inc" 22 | -------------------------------------------------------------------------------- /tests/nasm/movntps.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | myfloat0: 6 | dd 1.234567e20 7 | myfloat1: 8 | dd 2.345678e20 9 | myfloat2: 10 | dd 3.456789e20 11 | myfloat3: 12 | dd 4.567891e20 13 | myaddress: 14 | dd 0xdeadbeef 15 | %include "header.inc" 16 | 17 | movapd xmm0, [myfloat0] 18 | movntps [myaddress], xmm0 19 | movapd xmm1, [myaddress] 20 | 21 | %include "footer.inc" 22 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/argv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Set up arguments for main() and prepare environment variables 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU Library General Public License version 2. 6 | */ 7 | 8 | extern void __setup_args(void); 9 | extern void setup_args_progname(const char *args); 10 | extern void setup_env(char *env, int size); 11 | -------------------------------------------------------------------------------- /tests/nasm/jcxz.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov ecx, 0x10000 6 | jecxz cont1 7 | or eax, 1 8 | cont1: 9 | 10 | mov ecx, 0 11 | jecxz cont2 12 | or eax, 2 13 | cont2: 14 | 15 | mov ecx, 0x1 16 | jcxz cont3 17 | or eax, 4 18 | cont3: 19 | 20 | mov ecx, 0x10000 21 | jcxz cont4 22 | or eax, 8 23 | cont4: 24 | 25 | %include "footer.inc" 26 | -------------------------------------------------------------------------------- /tests/nasm/loopnz.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov ecx, 0x10042 6 | mov eax, 42 7 | start1: 8 | dec eax 9 | loopz start1 10 | 11 | mov ecx, 0x10005 12 | mov ebx, 51 13 | start2: 14 | dec ebx 15 | db 67h 16 | loopz start2 17 | 18 | mov ecx, 0x10005 19 | start3: 20 | or edx, 1 21 | db 67h 22 | loopz start3 23 | 24 | %include "footer.inc" 25 | -------------------------------------------------------------------------------- /tests/nasm/loopz.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov ecx, 0x10042 6 | mov eax, -1 7 | start1: 8 | inc eax 9 | loopz start1 10 | 11 | mov ecx, 0x10005 12 | mov ebx, -1 13 | start2: 14 | inc ebx 15 | db 67h 16 | loopz start2 17 | 18 | mov ecx, 0x10005 19 | start3: 20 | xor edx, edx 21 | db 67h 22 | loopz start3 23 | 24 | %include "footer.inc" 25 | -------------------------------------------------------------------------------- /tests/nasm/movd.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | myquad: 6 | dq 0x1234567890abcdef 7 | mydword: 8 | dd 0xcafebabe 9 | myaddress: 10 | dd 0xdeadbeef 11 | 12 | %include "header.inc" 13 | 14 | 15 | movd mm0, [mydword] 16 | movd [myaddress], mm0 17 | movd mm1, [myaddress] 18 | movd eax, mm0 19 | movd mm4, eax 20 | mov eax, 0x42 21 | movd mm6, eax 22 | 23 | %include "footer.inc" 24 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016, Red Hat Inc, Andrew Jones 3 | * 4 | * This work is licensed under the terms of the GNU LGPL, version 2. 5 | */ 6 | #include 7 | #include "util.h" 8 | 9 | int parse_keyval(char *s, long *val) 10 | { 11 | char *p; 12 | 13 | p = strchr(s, '='); 14 | if (!p) 15 | return -1; 16 | 17 | *val = atol(p+1); 18 | return p - s; 19 | } 20 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/smp.h: -------------------------------------------------------------------------------- 1 | #ifndef __SMP_H 2 | #define __SMP_H 3 | #include 4 | 5 | void smp_init(void); 6 | 7 | int cpu_count(void); 8 | int smp_id(void); 9 | int cpus_active(void); 10 | void on_cpu(int cpu, void (*function)(void *data), void *data); 11 | void on_cpu_async(int cpu, void (*function)(void *data), void *data); 12 | void on_cpus(void (*function)(void *data), void *data); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/asm-generic/spinlock.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASM_GENERIC_SPINLOCK_H_ 2 | #define _ASM_GENERIC_SPINLOCK_H_ 3 | 4 | struct spinlock { 5 | unsigned int v; 6 | }; 7 | 8 | static inline void spin_lock(struct spinlock *lock) 9 | { 10 | while (__sync_lock_test_and_set(&lock->v, 1)); 11 | } 12 | 13 | static inline void spin_unlock(struct spinlock *lock) 14 | { 15 | __sync_lock_release(&lock->v); 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /bios/fetch-and-build-seabios.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | git clone https://git.seabios.org/seabios.git || true 3 | (cd seabios && git checkout rel-1.16.2) 4 | 5 | cp seabios.config seabios/.config 6 | make -C seabios 7 | cp seabios/out/bios.bin seabios.bin 8 | cp seabios/out/vgabios.bin vgabios.bin 9 | 10 | cp seabios-debug.config seabios/.config 11 | make -C seabios 12 | cp seabios/out/bios.bin seabios-debug.bin 13 | cp seabios/out/vgabios.bin vgabios-debug.bin 14 | -------------------------------------------------------------------------------- /docs/profiling.md: -------------------------------------------------------------------------------- 1 | v86 has a built-in profiler, which instruments generated code to count certain 2 | events and types of instructions. It can be used by building with `make 3 | debug-with-profiler` and opening debug.html. 4 | 5 | For debugging networking, packet logging is available in the UI in both debug 6 | and release builds. The resulting `traffic.hex` file can be loaded in Wireshark 7 | using file -> import from hex -> tick direction indication, timestamp %s.%f. 8 | -------------------------------------------------------------------------------- /tests/nasm/pshufw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | myquad: 6 | dq 0xad0000ceadad00ff 7 | mydword: 8 | dd 0xcafebabe 9 | myaddress: 10 | dq 0x00adbeefc0de00ce 11 | 12 | %include "header.inc" 13 | 14 | movq mm0, [myquad] 15 | pshufw mm0, [myaddress], 0xAB 16 | pshufw mm1, [myaddress], 0xFE 17 | pshufw mm2, [myquad], 0xFF 18 | pshufw mm6, [myaddress], 0x19 19 | pshufw mm7, [myaddress], 0xB5 20 | %include "footer.inc" 21 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/types.h: -------------------------------------------------------------------------------- 1 | #ifndef __TYPES_H 2 | #define __TYPES_H 3 | 4 | #define DE_VECTOR 0 5 | #define DB_VECTOR 1 6 | #define BP_VECTOR 3 7 | #define OF_VECTOR 4 8 | #define BR_VECTOR 5 9 | #define UD_VECTOR 6 10 | #define NM_VECTOR 7 11 | #define DF_VECTOR 8 12 | #define TS_VECTOR 10 13 | #define NP_VECTOR 11 14 | #define SS_VECTOR 12 15 | #define GP_VECTOR 13 16 | #define PF_VECTOR 14 17 | #define MF_VECTOR 16 18 | #define MC_VECTOR 18 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /tests/nasm/cvtpi2ps.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad0low: 6 | dd 1 7 | quad0high: 8 | dd 2 9 | quad1low: 10 | dd -1234567 11 | quad1high: 12 | dd 0 13 | myaddress: 14 | dd 0xdeadbeef 15 | %include "header.inc" 16 | 17 | cvtpi2ps xmm0, [quad0low] 18 | ; fill xmm1 in order to ensure that the high quadword remain inchanged 19 | pshufd xmm1, xmm0, 0 20 | cvtpi2ps xmm1, [quad1low] 21 | 22 | %include "footer.inc" 23 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/libfdt/Makefile.libfdt: -------------------------------------------------------------------------------- 1 | # Makefile.libfdt 2 | # 3 | # This is not a complete Makefile of itself. Instead, it is designed to 4 | # be easily embeddable into other systems of Makefiles. 5 | # 6 | LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1 7 | LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h 8 | LIBFDT_VERSION = version.lds 9 | LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c 10 | LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) 11 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Fetch images", 8 | "type": "shell", 9 | "command": "wget -P images/ https://k.copy.sh/{linux3.iso,linux.iso,linux4.iso,buildroot-bzimage.bin,openbsd-floppy.img,kolibri.img,windows101.img,os8.img,freedos722.img}" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.swo 3 | tests/qemu/test-i386 4 | tests/jit-paging/test-jit 5 | *.map 6 | build/ 7 | closure-compiler/ 8 | images/ 9 | *.bak 10 | *.orig 11 | *.wasm 12 | *.o 13 | *.bin 14 | *.img 15 | *.fixture 16 | *.fuse_hidden* 17 | *.DS_Store 18 | node_modules/ 19 | Cargo.lock 20 | build-head 21 | src/rust/gen/interpreter.rs 22 | src/rust/gen/interpreter0f.rs 23 | src/rust/gen/analyzer.rs 24 | src/rust/gen/analyzer0f.rs 25 | src/rust/gen/jit.rs 26 | src/rust/gen/jit0f.rs 27 | bios/seabios 28 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/api/exception.hh: -------------------------------------------------------------------------------- 1 | #ifndef EXCEPTION_HH 2 | #define EXCEPTION_HH 3 | 4 | #include 5 | 6 | class errno_exception : public std::exception { 7 | public: 8 | explicit errno_exception(int err_no); 9 | int errno() const; 10 | virtual const char *what(); 11 | private: 12 | int _errno; 13 | char _buf[1000]; 14 | }; 15 | 16 | int try_main(int (*main)(int argc, char** argv), int argc, char** argv, 17 | int ret_on_exception = 127); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /tests/qemu/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CC_I386=$(CC) -m32 3 | CFLAGS=-Wall -O2 -g -fno-strict-aliasing -static -mmmx -msse 4 | LDFLAGS= 5 | 6 | 7 | # i386/x86_64 emulation test (test various opcodes) */ 8 | test-i386: test-i386.c test-i386-code16.S test-i386-vm86.S \ 9 | test-i386.h test-i386-shift.h test-i386-muldiv.h 10 | $(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ \ 11 | $( Page { Page(address >> 12) } 7 | pub fn to_address(self) -> u32 { self.0 << 12 } 8 | 9 | pub fn to_u32(self) -> u32 { self.0 } 10 | pub fn of_u32(page: u32) -> Page { Page(page) } 11 | 12 | pub fn address_range(self) -> RangeInclusive { 13 | self.to_address()..=self.to_address() + 4095 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/jit-paging/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | These tests map 2 adjacent pages to the exact same physical frame. Code is 4 | written to one page and executed from the other, then overwritten and executed 5 | again, in order to trigger cache activity. Unlike `/tests/jit/`, this folder is 6 | meant to test the JIT in protected mode with paging setup, not in real-mode. 7 | 8 | # Run 9 | 10 | - Obtain the `linux3.iso` image (see [Readme.md](../../Readme.md)) 11 | - Run `make jitpagingtests` in the root of the project 12 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "v86" 3 | version = "0.1.0" 4 | publish = false 5 | 6 | [features] 7 | default = [] 8 | profiler = [] 9 | 10 | [lib] 11 | crate-type = ["cdylib"] 12 | path = "src/rust/lib.rs" 13 | 14 | [profile.test] 15 | lto = false 16 | opt-level = 2 17 | overflow-checks = false 18 | 19 | [profile.dev] 20 | lto = true 21 | opt-level = 2 22 | panic = "abort" 23 | overflow-checks = false 24 | 25 | [profile.release] 26 | lto = true 27 | opt-level = 3 28 | incremental = false 29 | panic = "abort" 30 | -------------------------------------------------------------------------------- /src/rust/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(const_item_mutation)] 2 | 3 | #[macro_use] 4 | mod dbg; 5 | 6 | #[macro_use] 7 | mod paging; 8 | 9 | pub mod cpu; 10 | 11 | pub mod js_api; 12 | pub mod profiler; 13 | 14 | mod analysis; 15 | mod codegen; 16 | mod config; 17 | mod control_flow; 18 | mod cpu_context; 19 | mod gen; 20 | mod jit; 21 | mod jit_instructions; 22 | mod leb; 23 | mod modrm; 24 | mod opstats; 25 | mod page; 26 | mod prefix; 27 | mod regs; 28 | mod softfloat; 29 | mod state_flags; 30 | mod util; 31 | mod wasmgen; 32 | mod zstd; 33 | -------------------------------------------------------------------------------- /src/rust/prefix.rs: -------------------------------------------------------------------------------- 1 | pub const PREFIX_REPZ: u8 = 0b01000; 2 | pub const PREFIX_REPNZ: u8 = 0b10000; 3 | pub const PREFIX_MASK_REP: u8 = PREFIX_REPZ | PREFIX_REPNZ; 4 | 5 | pub const PREFIX_MASK_OPSIZE: u8 = 0b100000; 6 | pub const PREFIX_MASK_ADDRSIZE: u8 = 0b1000000; 7 | 8 | pub const PREFIX_66: u8 = PREFIX_MASK_OPSIZE; 9 | pub const PREFIX_67: u8 = PREFIX_MASK_ADDRSIZE; 10 | pub const PREFIX_F2: u8 = PREFIX_REPNZ; 11 | pub const PREFIX_F3: u8 = PREFIX_REPZ; 12 | 13 | pub const SEG_PREFIX_ZERO: u8 = 7; 14 | 15 | pub const PREFIX_MASK_SEGMENT: u8 = 0b111; 16 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyright (C) 2006 Qumranet. 2 | Copyright (C) 2007-2017 by various contributors (see source files for details) 3 | 4 | The kvm-unit-tests are free software; the whole package can be redistributed 5 | and/or modified under the terms of the GNU General Public License version 2 6 | as published by the Free Software Foundation. 7 | 8 | Many files in this directory and its subdirectories are also licensed under 9 | the less restrictive GNU LGPL, version 2, or other compatible licenses. See 10 | the individual files for details. 11 | -------------------------------------------------------------------------------- /tests/nasm/por.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80ad7fffffff 7 | quad2: 8 | dq 0x71ae01ff0f00ffbe 9 | quad3: 10 | dq 0xf100808080f0ff42 11 | mydword: 12 | dd 0xcafebabe 13 | myaddress: 14 | dq 0x00adbeefc0de00ce 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad2] 22 | 23 | por mm0, [quad2] 24 | por mm0, [quad1] 25 | por mm1, mm2 26 | por mm2, [quad1] 27 | por mm3, [quad1] 28 | 29 | 30 | %include "footer.inc" 31 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/chr-testdev.h: -------------------------------------------------------------------------------- 1 | #ifndef _CHR_TESTDEV_H_ 2 | #define _CHR_TESTDEV_H_ 3 | /* 4 | * chr-testdev is a driver for the chr-testdev qemu backend. 5 | * The chr-testdev backend exposes a simple control interface to 6 | * qemu for kvm-unit-tests accessible through virtio-console. 7 | * 8 | * Copyright (C) 2014, Red Hat Inc, Andrew Jones 9 | * 10 | * This work is licensed under the terms of the GNU LGPL, version 2. 11 | */ 12 | extern void chr_testdev_init(void); 13 | extern void chr_testdev_exit(int code); 14 | #endif 15 | -------------------------------------------------------------------------------- /tests/nasm/pandn.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80ad7fffffff 7 | quad2: 8 | dq 0x71ae01ff0f00ffbe 9 | quad3: 10 | dq 0xf100808080f0ff42 11 | mydword: 12 | dd 0xcafebabe 13 | myaddress: 14 | dq 0x00adbeefc0de00ce 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad2] 22 | 23 | pandn mm0, [quad2] 24 | pandn mm0, [quad1] 25 | pandn mm1, mm2 26 | pandn mm2, [quad1] 27 | pandn mm3, [quad1] 28 | 29 | 30 | %include "footer.inc" 31 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/setjmp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * setjmp/longjmp prototypes 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU Library General Public License version 2. 6 | */ 7 | #ifndef LIBCFLAT_SETJMP_H 8 | #define LIBCFLAT_SETJMP_H 1 9 | 10 | typedef struct jmp_buf_tag { 11 | long int regs[8]; 12 | } jmp_buf[1]; 13 | 14 | extern int setjmp (struct jmp_buf_tag env[1]); 15 | extern void longjmp (struct jmp_buf_tag env[1], int val) 16 | __attribute__ ((__noreturn__)); 17 | 18 | #endif /* setjmp.h */ 19 | -------------------------------------------------------------------------------- /.jshint.json: -------------------------------------------------------------------------------- 1 | { 2 | "esversion": 8, 3 | "globalstrict": true, 4 | "sub": true, 5 | "expr": true, 6 | "-W058": true, 7 | "-W080": true, 8 | "-W082": true, 9 | "-W079": true, 10 | "-W117": true, 11 | "-W054": true, 12 | "-W027": true, 13 | "-W040": true, 14 | "-W087": true, 15 | "-W008": true, 16 | "loopfunc": true, 17 | "shadow": true, 18 | "funcscope": true, 19 | "globals": { 20 | "Blob": false, 21 | "alert": false, 22 | "console": false 23 | }, 24 | "browser": true 25 | } 26 | -------------------------------------------------------------------------------- /tests/nasm/paddsb.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80ad7fffffff 7 | quad2: 8 | dq 0x71ae01ff0f00ffbe 9 | quad3: 10 | dq 0xf100808080f0ff42 11 | mydword: 12 | dd 0xcafebabe 13 | myaddress: 14 | dq 0x00adbeefc0de00ce 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad2] 22 | 23 | paddsb mm0, [quad2] 24 | paddsb mm0, [quad1] 25 | paddsb mm1, mm2 26 | paddsb mm2, [quad1] 27 | paddsb mm3, [quad1] 28 | 29 | 30 | %include "footer.inc" 31 | -------------------------------------------------------------------------------- /tests/nasm/paddsw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80ad7fffffff 7 | quad2: 8 | dq 0x71ae01ff0f00ffbe 9 | quad3: 10 | dq 0xf100808080f0ff42 11 | mydword: 12 | dd 0xcafebabe 13 | myaddress: 14 | dq 0x00adbeefc0de00ce 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad2] 22 | 23 | paddsw mm0, [quad2] 24 | paddsw mm0, [quad1] 25 | paddsw mm1, mm2 26 | paddsw mm2, [quad1] 27 | paddsw mm3, [quad1] 28 | 29 | 30 | %include "footer.inc" 31 | -------------------------------------------------------------------------------- /tests/nasm/paddusb.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80ad7fffffff 7 | quad2: 8 | dq 0x71ae01ff0f00ffbe 9 | quad3: 10 | dq 0xf100808080f0ff42 11 | mydword: 12 | dd 0xcafebabe 13 | myaddress: 14 | dq 0x00adbeefc0de00ce 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad2] 22 | 23 | paddusb mm0, [quad2] 24 | paddusb mm0, [quad1] 25 | paddusb mm1, mm2 26 | paddusb mm2, [quad1] 27 | paddusb mm3, [quad1] 28 | 29 | 30 | %include "footer.inc" 31 | -------------------------------------------------------------------------------- /tests/nasm/paddusw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80ad7fffffff 7 | quad2: 8 | dq 0x71ae01ff0f00ffbe 9 | quad3: 10 | dq 0xf100808080f0ff42 11 | mydword: 12 | dd 0xcafebabe 13 | myaddress: 14 | dq 0x00adbeefc0de00ce 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad2] 22 | 23 | paddusw mm0, [quad2] 24 | paddusw mm0, [quad1] 25 | paddusw mm1, mm2 26 | paddusw mm2, [quad1] 27 | paddusw mm3, [quad1] 28 | 29 | 30 | %include "footer.inc" 31 | -------------------------------------------------------------------------------- /tests/nasm/pcmpeqd.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80ad7fffffff 7 | quad2: 8 | dq 0x70ad80ad7fffffff 9 | quad3: 10 | dq 0xf100808080f0ff42 11 | mydword: 12 | dd 0xcafebabe 13 | myaddress: 14 | dq 0x00adbeefc0de00ce 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad2] 22 | 23 | pcmpeqd mm0, [quad2] 24 | pcmpeqd mm0, [quad1] 25 | pcmpeqd mm1, mm2 26 | pcmpeqd mm2, [quad1] 27 | pcmpeqd mm3, [quad1] 28 | 29 | 30 | %include "footer.inc" 31 | -------------------------------------------------------------------------------- /tests/nasm/pcmpeqw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80adad007fff 7 | quad2: 8 | dq 0x7fff00428000ffff 9 | quad3: 10 | dq 0x01008080f0f0ff42 11 | mydword: 12 | dd 0xcafebabe 13 | myaddress: 14 | dq 0x00adbeefc0de00ce 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad2] 22 | 23 | pcmpeqw mm0, [quad2] 24 | pcmpeqw mm0, [quad1] 25 | pcmpeqw mm1, mm2 26 | pcmpeqw mm2, [quad1] 27 | pcmpeqw mm3, [quad1] 28 | 29 | 30 | %include "footer.inc" 31 | -------------------------------------------------------------------------------- /tests/nasm/pcmpgtw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80adad007fff 7 | quad2: 8 | dq 0x7fff00428000ffff 9 | quad3: 10 | dq 0x01008080f0f0ff42 11 | mydword: 12 | dd 0xcafebabe 13 | myaddress: 14 | dq 0x00adbeefc0de00ce 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad2] 22 | 23 | pcmpgtw mm0, [quad2] 24 | pcmpgtw mm0, [quad1] 25 | pcmpgtw mm1, mm2 26 | pcmpgtw mm2, [quad1] 27 | pcmpgtw mm3, [quad1] 28 | 29 | 30 | %include "footer.inc" 31 | -------------------------------------------------------------------------------- /tests/nasm/pmulhw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80ad7fffffff 7 | quad2: 8 | dq 0x71ae01ff0f00ffbe 9 | quad3: 10 | dq 0xf100808080f0ff42 11 | mydword: 12 | dd 0xcafebabe 13 | myaddress: 14 | dq 0x00adbeefc0de00ce 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad2] 22 | 23 | pmulhw mm0, [quad2] 24 | pmulhw mm0, [quad1] 25 | pmulhw mm1, mm2 26 | pmulhw mm2, [quad1] 27 | pmulhw mm3, [quad1] 28 | 29 | 30 | %include "footer.inc" 31 | -------------------------------------------------------------------------------- /tests/nasm/pmullw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80ad7fffffff 7 | quad2: 8 | dq 0x71ae01ff0f00ffbe 9 | quad3: 10 | dq 0xf100808080f0ff42 11 | mydword: 12 | dd 0xcafebabe 13 | myaddress: 14 | dq 0x00adbeefc0de00ce 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad2] 22 | 23 | pmullw mm0, [quad2] 24 | pmullw mm0, [quad1] 25 | pmullw mm1, mm2 26 | pmullw mm2, [quad1] 27 | pmullw mm3, [quad1] 28 | 29 | 30 | %include "footer.inc" 31 | -------------------------------------------------------------------------------- /tests/nasm/psubsb.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80ad7fffffff 7 | quad2: 8 | dq 0x71ae01ff0f00ffbe 9 | quad3: 10 | dq 0xf100808080f0ff42 11 | mydword: 12 | dd 0xcafebabe 13 | myaddress: 14 | dq 0x00adbeefc0de00ce 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad2] 22 | 23 | psubsb mm0, [quad2] 24 | psubsb mm0, [quad1] 25 | psubsb mm1, mm2 26 | psubsb mm2, [quad1] 27 | psubsb mm3, [quad1] 28 | 29 | 30 | %include "footer.inc" 31 | -------------------------------------------------------------------------------- /tests/nasm/psubsw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80ad7fffffff 7 | quad2: 8 | dq 0x71ae01ff0f00ffbe 9 | quad3: 10 | dq 0xf100808080f0ff42 11 | mydword: 12 | dd 0xcafebabe 13 | myaddress: 14 | dq 0x00adbeefc0de00ce 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad2] 22 | 23 | psubsw mm0, [quad2] 24 | psubsw mm0, [quad1] 25 | psubsw mm1, mm2 26 | psubsw mm2, [quad1] 27 | psubsw mm3, [quad1] 28 | 29 | 30 | %include "footer.inc" 31 | -------------------------------------------------------------------------------- /tests/nasm/psubusb.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80ad7fffffff 7 | quad2: 8 | dq 0x71ae01ff0f00ffbe 9 | quad3: 10 | dq 0xf100808080f0ff42 11 | mydword: 12 | dd 0xcafebabe 13 | myaddress: 14 | dq 0x00adbeefc0de00ce 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad2] 22 | 23 | psubusb mm0, [quad2] 24 | psubusb mm0, [quad1] 25 | psubusb mm1, mm2 26 | psubusb mm2, [quad1] 27 | psubusb mm3, [quad1] 28 | 29 | 30 | %include "footer.inc" 31 | -------------------------------------------------------------------------------- /tests/nasm/psubusw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80ad7fffffff 7 | quad2: 8 | dq 0x71ae01ff0f00ffbe 9 | quad3: 10 | dq 0xf100808080f0ff42 11 | mydword: 12 | dd 0xcafebabe 13 | myaddress: 14 | dq 0x00adbeefc0de00ce 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad2] 22 | 23 | psubusw mm0, [quad2] 24 | psubusw mm0, [quad1] 25 | psubusw mm1, mm2 26 | psubusw mm2, [quad1] 27 | psubusw mm3, [quad1] 28 | 29 | 30 | %include "footer.inc" 31 | -------------------------------------------------------------------------------- /tests/nasm/packssdw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0xffffffff0fffffff 7 | quad2: 8 | dq 0x0000abcd80000000 9 | quad3: 10 | dq 0xaaaaaaaaffffff00 11 | mydword: 12 | dd 0xcafebabe 13 | myaddress: 14 | dq 0x00adbeefc0de00ce 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad2] 22 | 23 | packssdw mm0, mm2 24 | packssdw mm0, [quad1] 25 | packssdw mm1, [quad3] 26 | packssdw mm2, [quad1] 27 | packssdw mm3, [quad1] 28 | 29 | 30 | %include "footer.inc" 31 | -------------------------------------------------------------------------------- /tests/nasm/pcmpgtd.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80ad7fffffff 7 | quad2: 8 | dq 0x7fff00428000ffff 9 | quad3: 10 | dq 0xf100808080f0ff42 11 | mydword: 12 | dd 0xcafebabe 13 | myaddress: 14 | dq 0x00adbeefc0de00ce 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad2] 22 | 23 | pcmpgtd mm0, [quad2] 24 | pcmpgtd mm0, [quad1] 25 | pcmpgtd mm1, mm2 26 | pcmpgtd mm2, [quad1] 27 | pcmpgtd mm3, [quad1] 28 | 29 | 30 | %include "footer.inc" 31 | 32 | -------------------------------------------------------------------------------- /tests/nasm/packsswb.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x00ad00adad007fff 7 | quad2: 8 | dq 0x7fff00428000ffff 9 | quad3: 10 | dq 0x01008080f0f0ff42 11 | mydword: 12 | dd 0xcafebabe 13 | myaddress: 14 | dq 0x00adbeefc0de00ce 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad2] 22 | 23 | packsswb mm0, [quad3] 24 | packsswb mm0, [quad1] 25 | packsswb mm1, [quad3] 26 | packsswb mm2, [quad1] 27 | packsswb mm3, [quad1] 28 | 29 | 30 | %include "footer.inc" 31 | -------------------------------------------------------------------------------- /tests/nasm/cmpxchg.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | 5 | %include "header.inc" 6 | 7 | mov eax, 123456789 8 | mov ebx, 123456789 9 | mov edx, 123456789 10 | 11 | cmpxchg edx, ebx 12 | push eax 13 | push edx 14 | push ebx 15 | pushf 16 | and dword [esp], 8ffh 17 | 18 | cmpxchg ax, bx 19 | push eax 20 | push edx 21 | push ebx 22 | pushf 23 | and dword [esp], 8ffh 24 | 25 | cmpxchg al, bh 26 | push eax 27 | push edx 28 | push ebx 29 | pushf 30 | and dword [esp], 8ffh 31 | 32 | %include "footer.inc" 33 | -------------------------------------------------------------------------------- /tests/nasm/punpckhbw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | 6 | quad1: 7 | dq 0xccddccddad007fff 8 | quad2: 9 | dq 0xaabbaabbad007fff 10 | quad3: 11 | dq 0x00ff00ffad007fff 12 | 13 | mydword: 14 | dd 0xcafebabe 15 | myaddress: 16 | dq 0x00adbeefc0de00ce 17 | 18 | %include "header.inc" 19 | 20 | movq mm0, [quad1] 21 | movq mm1, [quad3] 22 | movq mm2, [quad2] 23 | movq mm3, [quad3] 24 | 25 | punpckhbw mm0, [myaddress] 26 | punpckhbw mm0, mm1 27 | punpckhbw mm1, [quad2] 28 | punpckhbw mm2, [quad1] 29 | punpckhbw mm3, [quad1] 30 | 31 | %include "footer.inc" 32 | -------------------------------------------------------------------------------- /tests/nasm/punpckhdq.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | 6 | quad1: 7 | dq 0xccddccddad007fff 8 | quad2: 9 | dq 0xaabbaabbad007fff 10 | quad3: 11 | dq 0x00ff00ffad007fff 12 | 13 | mydword: 14 | dd 0xcafebabe 15 | myaddress: 16 | dq 0x00adbeefc0de00ce 17 | 18 | %include "header.inc" 19 | 20 | movq mm0, [quad1] 21 | movq mm1, [quad3] 22 | movq mm2, [quad2] 23 | movq mm3, [quad3] 24 | 25 | punpckhdq mm0, [myaddress] 26 | punpckhdq mm0, mm1 27 | punpckhdq mm1, [quad2] 28 | punpckhdq mm2, [quad1] 29 | punpckhdq mm3, [quad1] 30 | 31 | %include "footer.inc" 32 | -------------------------------------------------------------------------------- /tests/nasm/punpckhwd.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | 6 | quad1: 7 | dq 0xccddccddad007fff 8 | quad2: 9 | dq 0xaabbaabbad007fff 10 | quad3: 11 | dq 0x00ff00ffad007fff 12 | 13 | mydword: 14 | dd 0xcafebabe 15 | myaddress: 16 | dq 0x00adbeefc0de00ce 17 | 18 | %include "header.inc" 19 | 20 | movq mm0, [quad1] 21 | movq mm1, [quad3] 22 | movq mm2, [quad2] 23 | movq mm3, [quad3] 24 | 25 | punpckhwd mm0, [myaddress] 26 | punpckhwd mm0, mm1 27 | punpckhwd mm1, [quad2] 28 | punpckhwd mm2, [quad1] 29 | punpckhwd mm3, [quad1] 30 | 31 | %include "footer.inc" 32 | -------------------------------------------------------------------------------- /src/rust/paging.rs: -------------------------------------------------------------------------------- 1 | pub type OrPageFault = Result; 2 | 3 | macro_rules! return_on_pagefault { 4 | ($expr:expr) => { 5 | match $expr { 6 | Ok(v) => v, 7 | Err(()) => return, 8 | } 9 | }; 10 | ($expr:expr, $ret:expr) => { 11 | match $expr { 12 | Ok(v) => v, 13 | Err(()) => return $ret, 14 | } 15 | }; 16 | } 17 | 18 | macro_rules! break_on_pagefault { 19 | ($expr:expr) => { 20 | match $expr { 21 | Ok(v) => v, 22 | Err(()) => break, 23 | } 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /tests/nasm/cvttps2pi.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | float0low: 6 | dd 2147483647.0 7 | float0high: 8 | dd -2147483648.0 9 | float1low: 10 | dd 1235.678 11 | float1high: 12 | dd 1325400064 13 | float2low: 14 | dd -54.321 15 | float2high: 16 | dd -12345.6 17 | float3low: 18 | dd 123.456 19 | float3high: 20 | dd 1234.5678 21 | myaddress: 22 | dd 0xdeadbeef 23 | %include "header.inc" 24 | 25 | movaps xmm0, [float0low] 26 | cvttps2pi mm0, xmm0 27 | cvttps2pi mm1, [float1low] 28 | cvttps2pi mm2, [float2low] 29 | cvttps2pi mm3, [float3low] 30 | 31 | %include "footer.inc" 32 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/setjmp64.S: -------------------------------------------------------------------------------- 1 | .globl setjmp 2 | setjmp: 3 | mov (%rsp), %rsi 4 | mov %rsi, (%rdi) 5 | mov %rsp, 0x8(%rdi) 6 | mov %rbp, 0x10(%rdi) 7 | mov %rbx, 0x18(%rdi) 8 | mov %r12, 0x20(%rdi) 9 | mov %r13, 0x28(%rdi) 10 | mov %r14, 0x30(%rdi) 11 | mov %r15, 0x38(%rdi) 12 | xor %eax, %eax 13 | ret 14 | 15 | .globl longjmp 16 | longjmp: 17 | mov %esi, %eax 18 | mov 0x38(%rdi), %r15 19 | mov 0x30(%rdi), %r14 20 | mov 0x28(%rdi), %r13 21 | mov 0x20(%rdi), %r12 22 | mov 0x18(%rdi), %rbx 23 | mov 0x10(%rdi), %rbp 24 | mov 0x8(%rdi), %rsp 25 | mov (%rdi), %rsi 26 | mov %rsi, (%rsp) 27 | ret 28 | -------------------------------------------------------------------------------- /tools/docker/exec/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.14 as v86-builder 2 | WORKDIR /v86 3 | 4 | RUN apk add --update curl clang make openjdk8 npm python3 5 | 6 | RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && PATH="${HOME}/.cargo/bin:${PATH}" rustup target add wasm32-unknown-unknown 7 | 8 | COPY . . 9 | 10 | RUN PATH="${HOME}/.cargo/bin:${PATH}" make all && rm -rf closure-compiler gen lib src tools .cargo cargo.toml Makefile 11 | 12 | FROM python:3.9.6-alpine3.14 13 | WORKDIR /v86 14 | 15 | COPY --from=v86-builder v86 . 16 | 17 | ARG PORT=8000 18 | CMD python3 -m http.server ${PORT} 19 | 20 | EXPOSE ${PORT} 21 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/setjmp32.S: -------------------------------------------------------------------------------- 1 | .globl setjmp 2 | setjmp: 3 | mov (%esp), %ecx // get return EIP 4 | mov 4(%esp), %eax // get jmp_buf 5 | mov %ecx, (%eax) 6 | mov %esp, 4(%eax) 7 | mov %ebp, 8(%eax) 8 | mov %ebx, 12(%eax) 9 | mov %esi, 16(%eax) 10 | mov %edi, 20(%eax) 11 | xor %eax, %eax 12 | ret 13 | 14 | .globl longjmp 15 | longjmp: 16 | mov 8(%esp), %eax // get return value 17 | mov 4(%esp), %ecx // get jmp_buf 18 | mov 20(%ecx), %edi 19 | mov 16(%ecx), %esi 20 | mov 12(%ecx), %ebx 21 | mov 8(%ecx), %ebp 22 | mov 4(%ecx), %esp 23 | mov (%ecx), %ecx // get saved EIP 24 | mov %ecx, (%esp) // and store it on the stack 25 | ret 26 | -------------------------------------------------------------------------------- /tests/nasm/paddb.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80ad7fffbaef 7 | quad2: 8 | dq 0x71ae010f0f000dbe 9 | quad3: 10 | dq 0xf100808080f0af42 11 | quad4: 12 | dq 0xffffffffffffffff 13 | mydword: 14 | dd 0xcafebabe 15 | myaddress: 16 | dq 0x00adbeefc0de00ce 17 | 18 | %include "header.inc" 19 | 20 | movq mm0, [quad1] 21 | movq mm1, [quad2] 22 | movq mm2, [quad3] 23 | movq mm3, [quad2] 24 | movq mm4, [quad4] 25 | 26 | paddb mm0, [quad2] 27 | paddb mm0, [quad1] 28 | paddb mm1, mm2 29 | paddb mm2, [quad1] 30 | paddb mm3, [quad1] 31 | paddb mm4, [quad4] 32 | 33 | 34 | %include "footer.inc" 35 | -------------------------------------------------------------------------------- /tests/nasm/paddd.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x00ad80ad0fffffff 7 | quad2: 8 | dq 0x71ae01ff0f00ffbe 9 | quad3: 10 | dq 0xf100808080f0ff42 11 | quad4: 12 | dq 0xffffffffffffffff 13 | mydword: 14 | dd 0xcafebabe 15 | myaddress: 16 | dq 0x00adbeefc0de00ce 17 | 18 | %include "header.inc" 19 | 20 | movq mm0, [quad1] 21 | movq mm1, [quad2] 22 | movq mm2, [quad3] 23 | movq mm3, [quad2] 24 | movq mm4, [quad4] 25 | 26 | paddd mm0, [quad2] 27 | paddd mm0, [quad1] 28 | paddd mm1, mm2 29 | paddd mm2, [quad1] 30 | paddd mm3, [quad1] 31 | paddd mm4, [quad4] 32 | 33 | 34 | %include "footer.inc" 35 | -------------------------------------------------------------------------------- /tests/nasm/psubb.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80ad7fffffff 7 | quad2: 8 | dq 0x71ae01ff0f00ffbe 9 | quad3: 10 | dq 0xf100808080f0ff42 11 | quad4: 12 | dq 0x8000800080008000 13 | mydword: 14 | dd 0xcafebabe 15 | myaddress: 16 | dq 0x00adbeefc0de00ce 17 | 18 | %include "header.inc" 19 | 20 | movq mm0, [quad1] 21 | movq mm1, [quad2] 22 | movq mm2, [quad3] 23 | movq mm3, [quad2] 24 | movq mm4, [quad4] 25 | 26 | psubb mm0, [quad2] 27 | psubb mm0, [quad1] 28 | psubb mm1, mm2 29 | psubb mm2, [quad1] 30 | psubb mm3, [quad1] 31 | psubb mm4, [quad4] 32 | 33 | 34 | %include "footer.inc" 35 | -------------------------------------------------------------------------------- /tests/nasm/psubd.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80ad7fffffff 7 | quad2: 8 | dq 0x71ae01ff0f00ffbe 9 | quad3: 10 | dq 0xf100808080f0ff42 11 | quad4: 12 | dq 0xffffffffffffffff 13 | mydword: 14 | dd 0xcafebabe 15 | myaddress: 16 | dq 0x00adbeefc0de00ce 17 | 18 | %include "header.inc" 19 | 20 | movq mm0, [quad1] 21 | movq mm1, [quad2] 22 | movq mm2, [quad3] 23 | movq mm3, [quad2] 24 | movq mm4, [quad4] 25 | 26 | psubd mm0, [quad2] 27 | psubd mm0, [quad1] 28 | psubd mm1, mm2 29 | psubd mm2, [quad1] 30 | psubd mm3, [quad1] 31 | psubd mm4, [quad4] 32 | 33 | 34 | %include "footer.inc" 35 | -------------------------------------------------------------------------------- /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM library/node:lts-bookworm 2 | 3 | ARG DEBIAN_FRONTEND=noninteractive 4 | RUN apt update && \ 5 | apt-get install -y nodejs nasm gdb unzip p7zip-full openjdk-17-jre wget python3 qemu-system-x86 git-core build-essential libc6-dev-i386-cross libc6-dev-i386 clang curl time 6 | RUN npm install -g jshint 7 | RUN curl https://sh.rustup.rs -sSf | sh -s -- -y 8 | RUN /root/.cargo/bin/rustup toolchain install stable && \ 9 | /root/.cargo/bin/rustup target add wasm32-unknown-unknown && \ 10 | /root/.cargo/bin/rustup component add rustfmt-preview && \ 11 | /root/.cargo/bin/rustup update && /root/.cargo/bin/rustup update nightly 12 | -------------------------------------------------------------------------------- /tests/nasm/pand.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0xad0000ceadad00ff 7 | quad2: 8 | dq 0xffffffffffffffff 9 | quad3: 10 | dq 0x0000000000000000 11 | quad4: 12 | dq 0x7fff8000ffff0808 13 | mydword: 14 | dd 0xcafebabe 15 | 16 | %include "header.inc" 17 | 18 | movq mm0, [quad1] 19 | movq mm1, [quad2] 20 | movq mm2, [quad3] 21 | movq mm3, [quad4] 22 | movq mm4, [quad1] 23 | 24 | pand mm1, [quad2] 25 | pand mm1, mm2 26 | pand mm2, [quad1] 27 | pand mm2, mm3 28 | pand mm3, [quad3] 29 | pand mm3, mm4 30 | pand mm4, [quad1] 31 | pand mm4, mm1 32 | pand mm4, mm3 33 | 34 | 35 | %include "footer.inc" 36 | -------------------------------------------------------------------------------- /tests/nasm/pmaddwd.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x70ad80ad7fffffff 7 | quad2: 8 | dq 0x71ae01ff0f00ffbe 9 | quad3: 10 | dq 0xf100808080f0ff42 11 | quad4: 12 | dq 0x8000800080008000 13 | mydword: 14 | dd 0xcafebabe 15 | myaddress: 16 | dq 0x00adbeefc0de00ce 17 | 18 | %include "header.inc" 19 | 20 | movq mm0, [quad1] 21 | movq mm1, [quad2] 22 | movq mm2, [quad3] 23 | movq mm3, [quad2] 24 | movq mm4, [quad4] 25 | 26 | pmaddwd mm0, [quad2] 27 | pmaddwd mm0, [quad1] 28 | pmaddwd mm1, mm2 29 | pmaddwd mm2, [quad1] 30 | pmaddwd mm3, [quad1] 31 | pmaddwd mm4, [quad4] 32 | 33 | 34 | %include "footer.inc" 35 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/smptest.c: -------------------------------------------------------------------------------- 1 | #include "libcflat.h" 2 | #include "smp.h" 3 | 4 | unsigned nipis; 5 | 6 | static void ipi_test(void *data) 7 | { 8 | int n = (long)data; 9 | 10 | printf("ipi called, cpu %d\n", n); 11 | if (n != smp_id()) 12 | printf("but wrong cpu %d\n", smp_id()); 13 | else 14 | nipis++; 15 | } 16 | 17 | int main() 18 | { 19 | int ncpus; 20 | int i; 21 | 22 | smp_init(); 23 | 24 | ncpus = cpu_count(); 25 | printf("found %d cpus\n", ncpus); 26 | for (i = 0; i < ncpus; ++i) 27 | on_cpu(i, ipi_test, (void *)(long)i); 28 | 29 | report("IPI to each CPU", nipis == ncpus); 30 | return report_summary(); 31 | } 32 | -------------------------------------------------------------------------------- /tests/nasm/bts-reg16.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov dword [esp], 0 6 | mov dword [esp+4], 0 7 | mov dword [esp+8], 0 8 | mov dword [esp+12], 0 9 | mov dword [esp+16], 0 10 | mov dword [esp+20], 0 11 | mov dword [esp+24], 0 12 | mov dword [esp+28], 0 13 | 14 | mov eax, 0 15 | bts word [esp], ax 16 | mov eax, -5 17 | bts word [esp + 4], ax 18 | mov eax, 1 19 | bts word [esp], ax 20 | mov eax, 31 21 | bts word [esp], ax 22 | mov eax, 32 23 | bts word [esp], ax 24 | mov eax, 63 25 | bts word [esp], ax 26 | mov eax, 99 27 | bts word [esp], ax 28 | 29 | %include "footer.inc" 30 | -------------------------------------------------------------------------------- /tests/nasm/btr-reg16.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov dword [esp], -1 6 | mov dword [esp+4], -1 7 | mov dword [esp+8], -1 8 | mov dword [esp+12], -1 9 | mov dword [esp+16], -1 10 | mov dword [esp+20], -1 11 | mov dword [esp+24], -1 12 | mov dword [esp+28], -1 13 | 14 | mov eax, 0 15 | btr word [esp], ax 16 | mov eax, -5 17 | btr word [esp + 4], ax 18 | mov eax, 1 19 | btr word [esp], ax 20 | mov eax, 31 21 | btr word [esp], ax 22 | mov eax, 32 23 | btr word [esp], ax 24 | mov eax, 63 25 | btr word [esp], ax 26 | mov eax, 99 27 | btr word [esp], ax 28 | 29 | %include "footer.inc" 30 | -------------------------------------------------------------------------------- /tools/docker/test-image/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:21.04 2 | 3 | RUN \ 4 | export DEBIAN_FRONTEND=noninteractive && \ 5 | dpkg --add-architecture i386 && \ 6 | apt-get update -qq && \ 7 | apt-get install -y nodejs nasm gdb unzip p7zip-full openjdk-8-jre wget python python3 qemu-system-x86 git-core build-essential libc6-dev-i386-cross libc6-dev-i386 clang curl time && \ 8 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && \ 9 | export PATH="$HOME/.cargo/bin:$PATH" && \ 10 | rustup toolchain install stable && \ 11 | rustup target add wasm32-unknown-unknown && \ 12 | rustup component add rustfmt-preview 13 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/api/api-sample.cc: -------------------------------------------------------------------------------- 1 | 2 | #include "kvmxx.hh" 3 | #include "identity.hh" 4 | #include "exception.hh" 5 | #include 6 | 7 | static int global = 0; 8 | 9 | static void set_global() 10 | { 11 | global = 1; 12 | } 13 | 14 | int test_main(int ac, char** av) 15 | { 16 | kvm::system system; 17 | kvm::vm vm(system); 18 | mem_map memmap(vm); 19 | identity::vm ident_vm(vm, memmap); 20 | kvm::vcpu vcpu(vm, 0); 21 | identity::vcpu thread(vcpu, set_global); 22 | vcpu.run(); 23 | printf("global %d\n", global); 24 | return global == 1 ? 0 : 1; 25 | } 26 | 27 | int main(int ac, char** av) 28 | { 29 | return try_main(test_main, ac, av); 30 | } 31 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/cmpxchg8b.c: -------------------------------------------------------------------------------- 1 | #include "ioram.h" 2 | #include "vm.h" 3 | #include "libcflat.h" 4 | #include "desc.h" 5 | #include "types.h" 6 | #include "processor.h" 7 | 8 | static void test_cmpxchg8b(u32 *mem) 9 | { 10 | mem[1] = 2; 11 | mem[0] = 1; 12 | asm("push %%ebx\n" 13 | "mov %[ebx_val], %%ebx\n" 14 | "lock cmpxchg8b (%0)\n" 15 | "pop %%ebx" : : "D" (mem), 16 | "d" (2), "a" (1), "c" (4), [ebx_val] "i" (3) : "memory"); 17 | report("cmpxchg8b", mem[0] == 3 && mem[1] == 4); 18 | } 19 | 20 | int main() 21 | { 22 | setup_vm(); 23 | setup_idt(); 24 | 25 | test_cmpxchg8b(phys_to_virt(read_cr3()) + 4088); 26 | return report_summary(); 27 | } 28 | -------------------------------------------------------------------------------- /tests/nasm/bts-reg32.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov dword [esp], 0 6 | mov dword [esp+4], 0 7 | mov dword [esp+8], 0 8 | mov dword [esp+12], 0 9 | mov dword [esp+16], 0 10 | mov dword [esp+20], 0 11 | mov dword [esp+24], 0 12 | mov dword [esp+28], 0 13 | 14 | mov eax, 0 15 | bts dword [esp], eax 16 | mov eax, -5 17 | bts dword [esp + 4], eax 18 | mov eax, 1 19 | bts dword [esp], eax 20 | mov eax, 31 21 | bts dword [esp], eax 22 | mov eax, 32 23 | bts dword [esp], eax 24 | mov eax, 63 25 | bts dword [esp], eax 26 | mov eax, 99 27 | bts dword [esp], eax 28 | 29 | %include "footer.inc" 30 | -------------------------------------------------------------------------------- /tests/nasm/btr-reg32.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov dword [esp], -1 6 | mov dword [esp+4], -1 7 | mov dword [esp+8], -1 8 | mov dword [esp+12], -1 9 | mov dword [esp+16], -1 10 | mov dword [esp+20], -1 11 | mov dword [esp+24], -1 12 | mov dword [esp+28], -1 13 | 14 | mov eax, 0 15 | btr dword [esp], eax 16 | mov eax, -5 17 | btr dword [esp + 4], eax 18 | mov eax, 1 19 | btr dword [esp], eax 20 | mov eax, 31 21 | btr dword [esp], eax 22 | mov eax, 32 23 | btr dword [esp], eax 24 | mov eax, 63 25 | btr dword [esp], eax 26 | mov eax, 99 27 | btr dword [esp], eax 28 | 29 | %include "footer.inc" 30 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/abort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014, Red Hat Inc, Andrew Jones 3 | * 4 | * This work is licensed under the terms of the GNU LGPL, version 2. 5 | */ 6 | #include "libcflat.h" 7 | 8 | /* 9 | * When exit(code) is invoked, qemu will exit with ((code << 1) | 1), 10 | * leaving us 128 exit status codes. To avoid confusion with signal 11 | * status, we further limit exit codes to those resulting in qemu 12 | * exiting with a status < 128. We give abort() the highest (127), 13 | * leaving the lower status codes for unit tests. 14 | */ 15 | #define ABORT_EXIT_STATUS 63 /* 127 exit status from qemu */ 16 | 17 | void abort(void) 18 | { 19 | exit(ABORT_EXIT_STATUS); 20 | } 21 | -------------------------------------------------------------------------------- /tests/nasm/pcmpeqb.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x00ad00adad007fff 7 | quad2: 8 | dq 0x7fff00428000ffff 9 | quad3: 10 | dq 0x01008080f0f0ff42 11 | quad4: 12 | dq 0x0000000000000000 13 | mydword: 14 | dd 0xcafebabe 15 | myaddress: 16 | dq 0x00adbeefc0de00ce 17 | 18 | %include "header.inc" 19 | 20 | movq mm0, [quad1] 21 | movq mm1, [quad2] 22 | movq mm2, [quad3] 23 | movq mm3, [quad4] 24 | movq mm4, [quad1] 25 | 26 | pcmpeqb mm1, [quad2] 27 | pcmpeqb mm1, mm2 28 | pcmpeqb mm2, [quad1] 29 | pcmpeqb mm2, mm3 30 | pcmpeqb mm3, [quad3] 31 | pcmpeqb mm3, mm4 32 | pcmpeqb mm4, [quad1] 33 | pcmpeqb mm4, mm1 34 | pcmpeqb mm4, mm3 35 | 36 | 37 | %include "footer.inc" 38 | -------------------------------------------------------------------------------- /examples/worker.js: -------------------------------------------------------------------------------- 1 | importScripts("../build/libv86.js"); 2 | 3 | var emulator = new V86({ 4 | wasm_path: "../build/v86.wasm", 5 | memory_size: 32 * 1024 * 1024, 6 | vga_memory_size: 2 * 1024 * 1024, 7 | bios: { 8 | url: "../bios/seabios.bin", 9 | }, 10 | vga_bios: { 11 | url: "../bios/vgabios.bin", 12 | }, 13 | cdrom: { 14 | url: "../images/linux4.iso", 15 | }, 16 | autostart: true, 17 | }); 18 | 19 | 20 | emulator.add_listener("serial0-output-byte", function(byte) 21 | { 22 | var chr = String.fromCharCode(byte); 23 | this.postMessage(chr); 24 | }.bind(this)); 25 | 26 | this.onmessage = function(e) 27 | { 28 | emulator.serial0_send(e.data); 29 | }; 30 | 31 | -------------------------------------------------------------------------------- /src/externs.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var global = {}; 4 | var process = { hrtime: function() {} }; 5 | 6 | /** 7 | * @param {string} name 8 | * @param {function()} processor 9 | */ 10 | var registerProcessor = function(name, processor) {}; 11 | 12 | /** @const */ 13 | var sampleRate = 0; 14 | 15 | var WabtModule = { 16 | readWasm: function(buf, opt) {}, 17 | generateNames: function() {}, 18 | applyNames: function() {}, 19 | toText: function() {}, 20 | }; 21 | var cs = { 22 | Capstone: function() {}, 23 | ARCH_X86: 0, 24 | MODE_16: 0, 25 | MODE_32: 0, 26 | disasm: { bytes: "", mnemonic: "", op_str: "", }, 27 | }; 28 | 29 | const Buffer = { 30 | allocUnsafe : function(length) {}, 31 | }; 32 | -------------------------------------------------------------------------------- /tests/nasm/mov_sreg.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | mydword: 6 | dd 0 7 | 8 | %include "header.inc" 9 | 10 | ; 32-bit register move should set higher bits to zero 11 | mov eax, -1 12 | mov eax, ss 13 | and eax, 0xffff0000 14 | 15 | mov ebx, -1 16 | db 66h 17 | mov ebx, ss 18 | and ebx, 0xffff0000 19 | 20 | ; 32-bit memory move should preserver higher bits 21 | mov dword [mydword], 0xdeadbeef 22 | mov [mydword], ss 23 | mov ecx, [mydword] 24 | and ecx, 0xffff0000 25 | 26 | mov dword [mydword+4], 0xdeadbeef 27 | db 66h 28 | mov [mydword+4], ss 29 | mov edx, [mydword+4] 30 | and edx, 0xffff0000 31 | 32 | %include "footer.inc" 33 | -------------------------------------------------------------------------------- /tests/qemu/LICENSE: -------------------------------------------------------------------------------- 1 | x86 CPU test 2 | 3 | Copyright (c) 2003 Fabrice Bellard 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, see . 17 | -------------------------------------------------------------------------------- /tools/docker/debian/boot-9p: -------------------------------------------------------------------------------- 1 | # 9p filesystem mounting -*- shell-script -*- 2 | 3 | mountroot() 4 | { 5 | wait_for_udev 10 6 | 7 | if [ ${readonly} = y ]; then 8 | roflag="-o ro" 9 | else 10 | roflag="-o rw" 11 | fi 12 | 13 | #echo "Running: mount -t 9p -o cache=mmap ${ROOT} ${rootmnt}" 14 | #mount -t 9p -o cache=mmap ${ROOT} ${rootmnt} 15 | echo "Running: mount -t 9p -o cache=fscache ${ROOT} ${rootmnt}" 16 | mount -t 9p -o cache=fscache ${ROOT} ${rootmnt} 17 | echo "mount finished with code $?" 18 | } 19 | 20 | mount_top() 21 | { 22 | echo top 23 | } 24 | 25 | mount_premount() 26 | { 27 | echo premount 28 | } 29 | 30 | mount_bottom() 31 | { 32 | echo bottom 33 | } 34 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "v86 dev container", 3 | "build": { 4 | "dockerfile": "Dockerfile", 5 | "args": { 6 | "VARIANT": "ubuntu" 7 | } 8 | }, 9 | "features": { 10 | "ghcr.io/devcontainers-contrib/features/curl-apt-get:1": {}, 11 | "ghcr.io/jungaretti/features/ripgrep:1": {} 12 | }, 13 | "customizations": { 14 | "vscode": { 15 | "extensions": [ 16 | "ms-azuretools.vscode-docker", 17 | "yzhang.markdown-all-in-one", 18 | "DavidAnson.vscode-markdownlint", 19 | "christian-kohler.npm-intellisense", 20 | "dbaeumer.vscode-eslint", 21 | "dustypomerleau.rust-syntax", 22 | "serayuzgur.crates", 23 | "ms-vscode.makefile-tools", 24 | "rust-lang.rust-analyzer" 25 | ] 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /tests/nasm/btc-reg16.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov dword [esp], 0x03479aef 6 | mov dword [esp+4], 0x03479aef 7 | mov dword [esp+8], 0x03479aef 8 | mov dword [esp+12], 0x03479aef 9 | mov dword [esp+16], 0x03479aef 10 | mov dword [esp+20], 0x03479aef 11 | mov dword [esp+24], 0x03479aef 12 | mov dword [esp+28], 0x03479aef 13 | 14 | mov eax, 0 15 | btc word [esp], ax 16 | mov eax, -5 17 | btc word [esp + 4], ax 18 | mov eax, 1 19 | btc word [esp], ax 20 | mov eax, 31 21 | btc word [esp], ax 22 | mov eax, 32 23 | btc word [esp], ax 24 | mov eax, 63 25 | btc word [esp], ax 26 | mov eax, 99 27 | btc word [esp], ax 28 | 29 | %include "footer.inc" 30 | -------------------------------------------------------------------------------- /tests/nasm/psubw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0xad0000ceadad00ff 7 | quad2: 8 | dq 0xffffffffffffffff 9 | quad3: 10 | dq 0x0000000000000000 11 | quad4: 12 | dq 0x7fff8000ffff0808 13 | myquad: 14 | dq 0xad0000ceadad00ff 15 | mydword: 16 | dd 0xcafebabe 17 | myaddress: 18 | dq 0x00adbeefc0de00ce 19 | 20 | %include "header.inc" 21 | 22 | movq mm0, [quad1] 23 | movq mm1, [quad2] 24 | movq mm2, [quad3] 25 | movq mm3, [quad4] 26 | movq mm4, [quad1] 27 | 28 | psubw mm1, [quad2] 29 | psubw mm1, mm2 30 | psubw mm2, [quad1] 31 | psubw mm2, mm3 32 | psubw mm3, [quad3] 33 | psubw mm3, mm4 34 | psubw mm4, [quad1] 35 | psubw mm4, mm1 36 | psubw mm4, mm3 37 | 38 | 39 | %include "footer.inc" 40 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/stack.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Header for stack related functions 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU Library General Public License version 2. 6 | */ 7 | #ifndef _STACK_H_ 8 | #define _STACK_H_ 9 | 10 | #include 11 | #include 12 | 13 | #ifdef HAVE_ARCH_BACKTRACE_FRAME 14 | extern int backtrace_frame(const void *frame, const void **return_addrs, 15 | int max_depth); 16 | #else 17 | static inline int 18 | backtrace_frame(const void *frame __unused, const void **return_addrs __unused, 19 | int max_depth __unused) 20 | { 21 | return 0; 22 | } 23 | #endif 24 | 25 | extern int backtrace(const void **return_addrs, int max_depth); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/asm/barrier.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASM_X86_BARRIER_H_ 2 | #define _ASM_X86_BARRIER_H_ 3 | /* 4 | * Copyright (C) 2016, Red Hat Inc, Alexander Gordeev 5 | * 6 | * This work is licensed under the terms of the GNU LGPL, version 2. 7 | */ 8 | 9 | #define mb() asm volatile("mfence":::"memory") 10 | #define rmb() asm volatile("lfence":::"memory") 11 | #define wmb() asm volatile("sfence":::"memory") 12 | 13 | #define smp_rmb() barrier() 14 | #define smp_wmb() barrier() 15 | 16 | /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ 17 | static inline void rep_nop(void) 18 | { 19 | asm volatile("rep; nop" ::: "memory"); 20 | } 21 | 22 | static inline void cpu_relax(void) 23 | { 24 | rep_nop(); 25 | } 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /tests/nasm/btc-reg32.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov dword [esp], 0x03479aef 6 | mov dword [esp+4], 0x03479aef 7 | mov dword [esp+8], 0x03479aef 8 | mov dword [esp+12], 0x03479aef 9 | mov dword [esp+16], 0x03479aef 10 | mov dword [esp+20], 0x03479aef 11 | mov dword [esp+24], 0x03479aef 12 | mov dword [esp+28], 0x03479aef 13 | 14 | mov eax, 0 15 | btc dword [esp], eax 16 | mov eax, -5 17 | btc dword [esp + 4], eax 18 | mov eax, 1 19 | btc dword [esp], eax 20 | mov eax, 31 21 | btc dword [esp], eax 22 | mov eax, 32 23 | btc dword [esp], eax 24 | mov eax, 63 25 | btc dword [esp], eax 26 | mov eax, 99 27 | btc dword [esp], eax 28 | 29 | %include "footer.inc" 30 | -------------------------------------------------------------------------------- /tests/nasm/bts-imm.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov dword [esp], 0 6 | mov dword [esp+4], 0 7 | mov dword [esp+8], 0 8 | mov dword [esp+12], 0 9 | mov dword [esp+16], 0 10 | mov dword [esp+20], 0 11 | mov dword [esp+24], 0 12 | mov dword [esp+28], 0 13 | 14 | bts word [esp], 0 15 | bts word [esp], 4 16 | bts word [esp], 9 17 | bts word [esp], 16 18 | bts word [esp], 31 19 | bts word [esp], 32 20 | bts word [esp], 55 21 | bts word [esp], 200 22 | 23 | bts dword [esp], 1 24 | bts dword [esp], 5 25 | bts dword [esp], 10 26 | bts dword [esp], 17 27 | bts dword [esp], 30 28 | bts dword [esp], 33 29 | bts dword [esp], 56 30 | bts dword [esp], 201 31 | 32 | %include "footer.inc" 33 | -------------------------------------------------------------------------------- /tests/nasm/psrad.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | dq0: 6 | dq 0x0102030405060708 7 | dq 0xffffaaaabbbbcccc 8 | dq1: 9 | dq 0x8d0000ceadad00ff 10 | dq 0x0123456789abcdef 11 | mydword: 12 | dd 0xcafebac0 13 | 14 | align 16 15 | shift1: 16 | dq 0x07 17 | dq 0 18 | shift2: 19 | dq -0x22 20 | dq 0 21 | 22 | %include "header.inc" 23 | 24 | movq mm0, [dq0] 25 | movq mm1, [dq0] 26 | movq mm2, [dq1] 27 | movq mm6, [dq1] 28 | 29 | movq xmm0, [dq0] 30 | movq xmm1, [dq0] 31 | movq xmm2, [dq1] 32 | movq xmm6, [dq1] 33 | 34 | psrad mm0, [shift1] 35 | psrad mm1, 0x18 36 | psrad mm2, [shift2] 37 | psrad mm6, 0x5 38 | 39 | psrad xmm0, [shift1] 40 | psrad xmm1, 0x18 41 | psrad xmm2, [shift2] 42 | psrad xmm6, 0x5 43 | 44 | %include "footer.inc" 45 | -------------------------------------------------------------------------------- /tests/nasm/maskmovq.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | 6 | quad0: 7 | dq 0x1234567890abcdef 8 | quad1: 9 | dq 0xffffffffffffffff 10 | mask0: 11 | dq 0x8080808080808080 12 | mask1: 13 | dq 0x10203080405080ff 14 | 15 | %include "header.inc" 16 | 17 | movq mm0, [quad0] 18 | movq mm1, [quad1] 19 | movq mm2, [quad0] 20 | movq mm3, [quad1] 21 | movq mm6, [mask0] 22 | movq mm7, [mask1] 23 | 24 | ;; Look out for size of extracted memory region 25 | mov esp, stack_top - 16 26 | 27 | mov edi, esp 28 | maskmovq mm0, mm6 29 | sub esp, 8 30 | 31 | mov edi, esp 32 | maskmovq mm1, mm6 33 | sub esp, 8 34 | 35 | mov edi, esp 36 | maskmovq mm2, mm7 37 | sub esp, 8 38 | 39 | mov edi, esp 40 | maskmovq mm3, mm7 41 | sub esp, 8 42 | 43 | %include "footer.inc" 44 | -------------------------------------------------------------------------------- /tests/nasm/btr-imm.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov dword [esp], -1 6 | mov dword [esp+4], -1 7 | mov dword [esp+8], -1 8 | mov dword [esp+12], -1 9 | mov dword [esp+16], -1 10 | mov dword [esp+20], -1 11 | mov dword [esp+24], -1 12 | mov dword [esp+28], -1 13 | 14 | btr word [esp], 0 15 | btr word [esp], 4 16 | btr word [esp], 9 17 | btr word [esp], 16 18 | btr word [esp], 31 19 | btr word [esp], 32 20 | btr word [esp], 55 21 | btr word [esp], 200 22 | 23 | btr dword [esp], 1 24 | btr dword [esp], 5 25 | btr dword [esp], 10 26 | btr dword [esp], 17 27 | btr dword [esp], 30 28 | btr dword [esp], 33 29 | btr dword [esp], 56 30 | btr dword [esp], 201 31 | 32 | %include "footer.inc" 33 | -------------------------------------------------------------------------------- /examples/worker.html: -------------------------------------------------------------------------------- 1 | 2 | Worker 3 | 4 | 30 | 31 | s 32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/stack.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int backtrace_frame(const void *frame, const void **return_addrs, int max_depth) 5 | { 6 | static int walking; 7 | int depth = 0; 8 | const unsigned long *bp = (unsigned long *) frame; 9 | 10 | if (walking) { 11 | printf("RECURSIVE STACK WALK!!!\n"); 12 | return 0; 13 | } 14 | walking = 1; 15 | 16 | for (depth = 0; bp && depth < max_depth; depth++) { 17 | return_addrs[depth] = (void *) bp[1]; 18 | if (return_addrs[depth] == 0) 19 | break; 20 | bp = (unsigned long *) bp[0]; 21 | } 22 | 23 | walking = 0; 24 | return depth; 25 | } 26 | 27 | int backtrace(const void **return_addrs, int max_depth) 28 | { 29 | return backtrace_frame(__builtin_frame_address(0), return_addrs, 30 | max_depth); 31 | } 32 | -------------------------------------------------------------------------------- /tests/nasm/psraw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | mydq0: 6 | dq 0xad0000ceadad00ff 7 | dq 0xff00dadaec0000da 8 | mydq1: 9 | dq 0x0102030405060708 10 | dq 0x090a0b0c0d0e0f10 11 | mydword: 12 | dd 0xcafebac0 13 | 14 | align 16 15 | shift0: 16 | dq 0x07 17 | dq 0 18 | shift1: 19 | dq -0x22 20 | dq 0 21 | 22 | %include "header.inc" 23 | 24 | movq mm0, [mydq0] 25 | movq mm1, [mydq0] 26 | movq mm2, [mydq1] 27 | movq mm6, [mydq1] 28 | 29 | movq xmm0, [mydq0] 30 | movq xmm1, [mydq0] 31 | movq xmm2, [mydq1] 32 | movq xmm6, [mydq1] 33 | 34 | psraw mm0, [shift1] 35 | psraw mm1, 18 36 | psraw mm2, [shift0] 37 | psraw mm6, 0x5 38 | 39 | psraw xmm0, [shift1] 40 | psraw xmm1, 18 41 | psraw xmm2, [shift0] 42 | psraw xmm6, 0x5 43 | 44 | %include "footer.inc" 45 | -------------------------------------------------------------------------------- /tests/nasm/psrld.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | mydq0: 6 | dq 0xad0000ceadad00ff 7 | dq 0xff00dadaec0000da 8 | mydq1: 9 | dq 0x0102030405060708 10 | dq 0x090a0b0c0d0e0f10 11 | mydword: 12 | dd 0xcafebac0 13 | 14 | align 16 15 | shift0: 16 | dq 0x07 17 | dq 0 18 | shift1: 19 | dq -0x22 20 | dq 0 21 | 22 | %include "header.inc" 23 | 24 | movq mm0, [mydq0] 25 | movq mm1, [mydq0] 26 | movq mm2, [mydq1] 27 | movq mm6, [mydq1] 28 | 29 | movq xmm0, [mydq0] 30 | movq xmm1, [mydq0] 31 | movq xmm2, [mydq1] 32 | movq xmm6, [mydq1] 33 | 34 | psrld mm0, [shift1] 35 | psrld mm1, 0xff 36 | psrld mm2, [shift0] 37 | psrld mm6, 0x5 38 | 39 | psrld xmm0, [shift1] 40 | psrld xmm1, 0xff 41 | psrld xmm2, [shift0] 42 | psrld xmm6, 0x5 43 | 44 | %include "footer.inc" 45 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/linux/const.h: -------------------------------------------------------------------------------- 1 | /* const.h: Macros for dealing with constants. */ 2 | 3 | #ifndef _LINUX_CONST_H 4 | #define _LINUX_CONST_H 5 | 6 | /* Some constant macros are used in both assembler and 7 | * C code. Therefore we cannot annotate them always with 8 | * 'UL' and other type specifiers unilaterally. We 9 | * use the following macros to deal with this. 10 | * 11 | * Similarly, _AT() will cast an expression with a type in C, but 12 | * leave it unchanged in asm. 13 | */ 14 | 15 | #ifdef __ASSEMBLY__ 16 | #define _AC(X,Y) X 17 | #define _AT(T,X) X 18 | #else 19 | #define __AC(X,Y) (X##Y) 20 | #define _AC(X,Y) __AC(X,Y) 21 | #define _AT(T,X) ((T)(X)) 22 | #endif 23 | 24 | #define _BITUL(x) (_AC(1,UL) << (x)) 25 | #define _BITULL(x) (_AC(1,ULL) << (x)) 26 | 27 | #endif /* !(_LINUX_CONST_H) */ 28 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/asm-generic/barrier.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASM_BARRIER_H_ 2 | #define _ASM_BARRIER_H_ 3 | /* 4 | * asm-generic/barrier.h 5 | * 6 | * Copyright (C) 2016, Red Hat Inc, Alexander Gordeev 7 | * 8 | * This work is licensed under the terms of the GNU LGPL, version 2. 9 | */ 10 | 11 | #ifndef mb 12 | #define mb() asm volatile("":::"memory") 13 | #endif 14 | #ifndef rmb 15 | #define rmb() asm volatile("":::"memory") 16 | #endif 17 | #ifndef wmb 18 | #define wmb() asm volatile("":::"memory") 19 | #endif 20 | 21 | #ifndef smp_mb 22 | #define smp_mb() mb() 23 | #endif 24 | #ifndef smp_rmb 25 | #define smp_rmb() rmb() 26 | #endif 27 | #ifndef smp_wmb 28 | #define smp_wmb() wmb() 29 | #endif 30 | 31 | #ifndef cpu_relax 32 | #define cpu_relax() asm volatile ("":::"memory") 33 | #endif 34 | 35 | #endif /* _ASM_BARRIER_H_ */ 36 | -------------------------------------------------------------------------------- /tests/nasm/pmuludq.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | dword1: 6 | dd 0x00000002 7 | dword2: 8 | dd 0xFFFFFF11 9 | dword3: 10 | dd 0xFFF00000 11 | dword4: 12 | dd 0x0000FFFF 13 | dword5: 14 | dd 0xFFFFFFFF 15 | mydword: 16 | dd 0xcafebabe 17 | myaddress: 18 | dq 0x00adbeefc0de00ce 19 | qword1: 20 | dq 0xffffffff00000001 21 | %include "header.inc" 22 | 23 | movd mm0, [dword1] 24 | movd mm1, [dword2] 25 | movd mm2, [dword1] 26 | movd mm3, [dword2] 27 | movd mm4, [dword4] 28 | movd mm5, [dword5] 29 | 30 | pmuludq mm0, [mydword] 31 | pmuludq mm2, mm1 32 | pmuludq mm3, [dword3] 33 | pmuludq mm4, [dword3] 34 | pmuludq mm5, [dword5] 35 | 36 | movd xmm1, [dword5] 37 | pshufd xmm1, xmm1, 0 38 | pmuludq xmm1, xmm1 39 | 40 | movd xmm2, [dword4] 41 | pmuludq xmm2, xmm1 42 | 43 | %include "footer.inc" 44 | -------------------------------------------------------------------------------- /tests/nasm/push.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | myaddress: 6 | dd 0xdeadbeef 7 | 8 | %include "header.inc" 9 | 10 | ;; push r/m - push edx 11 | db 0xff 12 | db 0xf2 13 | 14 | ;; push r/m - push bx 15 | db 0x66 16 | db 0xff 17 | db 0xf3 18 | 19 | ;; push imm 20 | push 0xdeadbeef 21 | push WORD 0xd00d 22 | 23 | ;; push r/m - mem 24 | push DWORD [myaddress] 25 | lea eax, [myaddress] 26 | push WORD [eax] 27 | 28 | ;; push reg 29 | mov ecx, 0xcafe 30 | push cx 31 | push ecx 32 | 33 | xor eax, eax 34 | 35 | pop ax 36 | pop eax 37 | pop cx 38 | pop ecx 39 | pop dx 40 | pop ebx 41 | pop si 42 | pop di 43 | 44 | %include "footer.inc" 45 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/api/exception.cc: -------------------------------------------------------------------------------- 1 | #include "exception.hh" 2 | #include 3 | #include 4 | 5 | errno_exception::errno_exception(int errno) 6 | : _errno(errno) 7 | { 8 | } 9 | 10 | int errno_exception::errno() const 11 | { 12 | return _errno; 13 | } 14 | 15 | const char *errno_exception::what() 16 | { 17 | std::snprintf(_buf, sizeof _buf, "error: %s (%d)", 18 | std::strerror(_errno), _errno); 19 | return _buf; 20 | } 21 | 22 | int try_main(int (*main)(int argc, char** argv), int argc, char** argv, 23 | int ret_on_exception) 24 | { 25 | try { 26 | return main(argc, argv); 27 | } catch (std::exception& e) { 28 | std::fprintf(stderr, "exception: %s\n", e.what()); 29 | } catch (...) { 30 | std::fprintf(stderr, "unknown exception\n"); 31 | } 32 | return ret_on_exception; 33 | } 34 | -------------------------------------------------------------------------------- /tests/nasm/pcmpgtb.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x00ad00adad007fff 7 | quad2: 8 | dq 0x7fff00428000ffff 9 | quad3: 10 | dq 0x01008080f0f0ff42 11 | quad4: 12 | dq 0x0000000000000000 13 | mydword: 14 | dd 0xcafebabe 15 | myaddress: 16 | dq 0x00adbeefc0de00ce 17 | 18 | %include "header.inc" 19 | 20 | movq mm0, [quad1] 21 | movq mm1, [quad2] 22 | movq mm2, [quad3] 23 | movq mm3, [quad4] 24 | movq mm4, [quad1] 25 | movq mm5, [quad2] 26 | movq mm6, [quad3] 27 | movq mm7, [quad4] 28 | 29 | pcmpgtb mm4, mm0 30 | pcmpgtb mm5, mm1 31 | pcmpgtb mm6, mm2 32 | pcmpgtb mm7, mm3 33 | pcmpgtb mm0, [quad2] 34 | pcmpgtb mm1, [quad3] 35 | pcmpgtb mm2, [quad4] 36 | pcmpgtb mm3, [quad1] 37 | pcmpgtb mm0, mm5 38 | pcmpgtb mm1, mm6 39 | pcmpgtb mm2, mm7 40 | pcmpgtb mm3, mm4 41 | 42 | %include "footer.inc" 43 | -------------------------------------------------------------------------------- /tests/nasm/pxor.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0xad0000ceadad00ff 7 | quad2: 8 | dq 0xffffffffffffffff 9 | quad3: 10 | dq 0x0000000000000000 11 | quad4: 12 | dq 0x7fff8000ffff0808 13 | myquad: 14 | dq 0xad0000ceadad00ff 15 | mydword: 16 | dd 0xcafebabe 17 | myaddress: 18 | dq 0x00adbeefc0de00ce 19 | 20 | %include "header.inc" 21 | 22 | movq mm0, [quad1] 23 | movq mm1, [quad2] 24 | movq mm2, [quad3] 25 | movq mm3, [quad4] 26 | movq mm4, [quad1] 27 | movq mm5, [quad2] 28 | movq mm6, [quad3] 29 | movq mm7, [quad4] 30 | 31 | pxor mm4, mm0 32 | pxor mm5, mm1 33 | pxor mm6, mm2 34 | pxor mm7, mm3 35 | pxor mm0, [quad2] 36 | pxor mm1, [quad3] 37 | pxor mm2, [quad4] 38 | pxor mm3, [quad1] 39 | pxor mm0, mm5 40 | pxor mm1, mm6 41 | pxor mm2, mm7 42 | pxor mm3, mm4 43 | 44 | %include "footer.inc" 45 | -------------------------------------------------------------------------------- /tests/nasm/btc-imm.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | %include "header.inc" 4 | 5 | mov dword [esp], 0x03479aef 6 | mov dword [esp+4], 0x03479aef 7 | mov dword [esp+8], 0x03479aef 8 | mov dword [esp+12], 0x03479aef 9 | mov dword [esp+16], 0x03479aef 10 | mov dword [esp+20], 0x03479aef 11 | mov dword [esp+24], 0x03479aef 12 | mov dword [esp+28], 0x03479aef 13 | 14 | btc word [esp], 0 15 | btc word [esp], 4 16 | btc word [esp], 9 17 | btc word [esp], 16 18 | btc word [esp], 31 19 | btc word [esp], 32 20 | btc word [esp], 55 21 | btc word [esp], 200 22 | 23 | btc dword [esp], 1 24 | btc dword [esp], 5 25 | btc dword [esp], 10 26 | btc dword [esp], 17 27 | btc dword [esp], 30 28 | btc dword [esp], 33 29 | btc dword [esp], 56 30 | btc dword [esp], 201 31 | 32 | %include "footer.inc" 33 | -------------------------------------------------------------------------------- /tests/nasm/pslld.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | mydq0: 6 | dq 0xad0000ceadad00ff 7 | dq 0xff00dadaec0000da 8 | mydq1: 9 | dq 0x0102030405060708 10 | dq 0x090a0b0c0d0e0f10 11 | mydword: 12 | dd 0xcafebac0 13 | shift0: 14 | dq 0x07 15 | shift1: 16 | dq -0x22 17 | 18 | align 16 19 | shift2: 20 | dq 0x07 21 | dq 0 22 | shift3: 23 | dq -0x22 24 | dq 0 25 | 26 | %include "header.inc" 27 | 28 | movq mm0, [mydq0] 29 | movq mm1, [mydq0] 30 | movq mm2, [mydq1] 31 | movq mm6, [mydq1] 32 | 33 | movq xmm0, [mydq0] 34 | movq xmm1, [mydq0] 35 | movq xmm2, [mydq1] 36 | movq xmm6, [mydq1] 37 | 38 | pslld mm0, [shift0] 39 | pslld mm1, 30 40 | pslld mm2, [shift1] 41 | pslld mm6, 0x5 42 | 43 | pslld xmm0, [shift2] 44 | pslld xmm1, 30 45 | pslld xmm2, [shift3] 46 | pslld xmm6, 0x5 47 | 48 | %include "footer.inc" 49 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/util.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTIL_H_ 2 | #define _UTIL_H_ 3 | /* 4 | * Collection of utility functions to share between unit tests. 5 | * 6 | * Copyright (C) 2016, Red Hat Inc, Andrew Jones 7 | * 8 | * This work is licensed under the terms of the GNU LGPL, version 2. 9 | */ 10 | 11 | /* 12 | * parse_keyval extracts the integer from a string formatted as 13 | * string=integer. This is useful for passing expected values to 14 | * the unit test on the command line, i.e. it helps parse QEMU 15 | * command lines that include something like -append var1=1 var2=2 16 | * @s is the input string, likely a command line parameter, and 17 | * @val is a pointer to where the integer will be stored. 18 | * 19 | * Returns the offset of the '=', or -1 if no keyval pair is found. 20 | */ 21 | extern int parse_keyval(char *s, long *val); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /tests/nasm/punpckldq.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x00ad00adad007fff 7 | quad2: 8 | dq 0xac4b1b9de29df0ff 9 | quad3: 10 | dq 0x01008080f0f0ff42 11 | quad4: 12 | dq 0x0123456789abcdef 13 | mydword: 14 | dd 0xcafebabe 15 | myaddress: 16 | dq 0x00adbeefc0de00ce 17 | 18 | %include "header.inc" 19 | 20 | movq mm0, [quad1] 21 | movq mm1, [quad2] 22 | movq mm2, [quad3] 23 | movq mm3, [quad4] 24 | movq mm4, [quad1] 25 | movq mm5, [quad2] 26 | movq mm6, [quad3] 27 | movq mm7, [quad4] 28 | 29 | punpckldq mm4, mm0 30 | punpckldq mm5, mm1 31 | punpckldq mm6, mm2 32 | punpckldq mm7, mm3 33 | punpckldq mm0, [quad2] 34 | punpckldq mm1, [quad3] 35 | punpckldq mm2, [quad4] 36 | punpckldq mm3, [quad1] 37 | punpckldq mm0, mm5 38 | punpckldq mm1, mm6 39 | punpckldq mm2, mm7 40 | punpckldq mm3, mm4 41 | 42 | %include "footer.inc" 43 | -------------------------------------------------------------------------------- /tests/nasm/punpcklwd.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0x00ad00adad007fff 7 | quad2: 8 | dq 0xac4b1b9de29df0ff 9 | quad3: 10 | dq 0x01008080f0f0ff42 11 | quad4: 12 | dq 0x0123456789abcdef 13 | mydword: 14 | dd 0xcafebabe 15 | myaddress: 16 | dq 0x00adbeefc0de00ce 17 | 18 | %include "header.inc" 19 | 20 | movq mm0, [quad1] 21 | movq mm1, [quad2] 22 | movq mm2, [quad3] 23 | movq mm3, [quad4] 24 | movq mm4, [quad1] 25 | movq mm5, [quad2] 26 | movq mm6, [quad3] 27 | movq mm7, [quad4] 28 | 29 | punpcklwd mm4, mm0 30 | punpcklwd mm5, mm1 31 | punpcklwd mm6, mm2 32 | punpcklwd mm7, mm3 33 | punpcklwd mm0, [quad2] 34 | punpcklwd mm1, [quad3] 35 | punpcklwd mm2, [quad4] 36 | punpcklwd mm3, [quad1] 37 | punpcklwd mm0, mm5 38 | punpcklwd mm1, mm6 39 | punpcklwd mm2, mm7 40 | punpcklwd mm3, mm4 41 | 42 | %include "footer.inc" 43 | -------------------------------------------------------------------------------- /examples/debian.html: -------------------------------------------------------------------------------- 1 | 2 | Debian 3 | 4 | 5 | 21 | 22 | 23 |
24 |
25 | 26 |
27 | -------------------------------------------------------------------------------- /tests/nasm/psrlw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | mydq0: 6 | dq 0xad0000ceadad00ff 7 | dq 0xff00dadaec0000da 8 | mydq1: 9 | dq 0x0102030405060708 10 | dq 0x090a0b0c0d0e0f10 11 | mydword: 12 | dd 0xcafebac0 13 | 14 | align 16 15 | shift0: 16 | dq 0x07 17 | dq 0 18 | shift1: 19 | dq -0x22 20 | dq 0 21 | 22 | %include "header.inc" 23 | 24 | movq mm0, [mydq0] 25 | movq mm1, [mydq0] 26 | movq mm2, [mydq1] 27 | movq mm3, [mydq1] 28 | movq mm6, [mydq1] 29 | 30 | movq xmm0, [mydq0] 31 | movq xmm1, [mydq0] 32 | movq xmm2, [mydq1] 33 | movq xmm3, [mydq1] 34 | movq xmm6, [mydq1] 35 | 36 | psrlw mm0, [shift1] 37 | psrlw mm1, 30 38 | psrlw mm2, [shift0] 39 | psrlw mm3, 12 40 | psrlw mm6, 0x5 41 | 42 | psrlw xmm0, [shift1] 43 | psrlw xmm1, 30 44 | psrlw xmm2, [shift0] 45 | psrlw xmm3, 12 46 | psrlw xmm6, 0x5 47 | 48 | %include "footer.inc" 49 | -------------------------------------------------------------------------------- /tests/api/test.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD; 5 | 6 | const fs = require("fs"); 7 | var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86; 8 | 9 | process.on("unhandledRejection", exn => { throw exn; }); 10 | 11 | const emulator = new V86({ 12 | bios: { url: __dirname + "/../../bios/seabios.bin" }, 13 | vga_bios: { url: __dirname + "/../../bios/vgabios.bin" }, 14 | fda: { url: __dirname + "/../../images/freedos722.img", async: true }, 15 | network_relay_url: "", 16 | autostart: true, 17 | memory_size: 32 * 1024 * 1024, 18 | filesystem: {}, 19 | log_level: -641, 20 | disable_jit: +process.env.DISABLE_JIT, 21 | screen_dummy: true, 22 | }); 23 | 24 | setInterval(() => { 25 | console.log(emulator.screen_adapter.get_text_screen()); 26 | }, 500); 27 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/asm-generic/page.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASM_GENERIC_PAGE_H_ 2 | #define _ASM_GENERIC_PAGE_H_ 3 | /* 4 | * asm-generic/page.h 5 | * adapted from the Linux kernel's include/asm-generic/page.h 6 | * 7 | * Copyright (C) 2017, Red Hat Inc, Andrew Jones 8 | * 9 | * This work is licensed under the terms of the GNU GPL, version 2. 10 | */ 11 | 12 | #include 13 | 14 | #define PAGE_SHIFT 12 15 | #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) 16 | #define PAGE_MASK (~(PAGE_SIZE-1)) 17 | 18 | #ifndef __ASSEMBLY__ 19 | 20 | #define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE) 21 | 22 | #define __va(x) ((void *)((unsigned long) (x))) 23 | #define __pa(x) ((unsigned long) (x)) 24 | #define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) 25 | #define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT) 26 | 27 | #endif /* !__ASSEMBLY__ */ 28 | 29 | #endif /* _ASM_GENERIC_PAGE_H_ */ 30 | -------------------------------------------------------------------------------- /tests/nasm/packuswb.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0xad0000ceadad00ff 7 | quad2: 8 | dq 0xffffffffffffffff 9 | quad3: 10 | dq 0x0000000000000000 11 | quad4: 12 | dq 0x7fff8000ffff0808 13 | myquad: 14 | dq 0x00ad00adad007fff 15 | mydword: 16 | dd 0xcafebabe 17 | myaddress: 18 | dq 0x00adbeefc0de00ce 19 | 20 | %include "header.inc" 21 | 22 | movq mm0, [quad1] 23 | movq mm1, [quad2] 24 | movq mm2, [quad3] 25 | movq mm3, [quad4] 26 | movq mm4, [quad1] 27 | movq mm5, [quad2] 28 | movq mm6, [quad3] 29 | movq mm7, [quad4] 30 | 31 | packuswb mm4, mm0 32 | packuswb mm5, mm1 33 | packuswb mm6, mm2 34 | packuswb mm7, mm3 35 | packuswb mm0, [quad2] 36 | packuswb mm1, [quad3] 37 | packuswb mm2, [quad4] 38 | packuswb mm3, [quad1] 39 | packuswb mm0, mm5 40 | packuswb mm1, mm6 41 | packuswb mm2, mm7 42 | packuswb mm3, mm4 43 | 44 | %include "footer.inc" 45 | -------------------------------------------------------------------------------- /tests/nasm/punpcklbw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0xad0000ceadad00ff 7 | quad2: 8 | dq 0xffffffffffffffff 9 | quad3: 10 | dq 0x0000000000000000 11 | quad4: 12 | dq 0x7fff8000ffff0808 13 | myquad: 14 | dq 0x00ad00adad007fff 15 | mydword: 16 | dd 0xcafebabe 17 | myaddress: 18 | dq 0x00adbeefc0de00ce 19 | 20 | %include "header.inc" 21 | 22 | movq mm0, [quad1] 23 | movq mm1, [quad2] 24 | movq mm2, [quad3] 25 | movq mm3, [quad4] 26 | movq mm4, [quad1] 27 | movq mm5, [quad2] 28 | movq mm6, [quad3] 29 | movq mm7, [quad4] 30 | 31 | punpcklbw mm4, mm0 32 | punpcklbw mm5, mm1 33 | punpcklbw mm6, mm2 34 | punpcklbw mm7, mm3 35 | punpcklbw mm0, [quad2] 36 | punpcklbw mm1, [quad3] 37 | punpcklbw mm2, [quad4] 38 | punpcklbw mm3, [quad1] 39 | punpcklbw mm0, mm5 40 | punpcklbw mm1, mm6 41 | punpcklbw mm2, mm7 42 | punpcklbw mm3, mm4 43 | 44 | %include "footer.inc" 45 | -------------------------------------------------------------------------------- /tests/nasm/cvtps2pi.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | float0low: 6 | dd 12345.678 7 | float0high: 8 | dd 1234.5 9 | float1low: 10 | dd 0x80000001.0 11 | float1high: 12 | dd -2147483130.0 13 | mxcsr: 14 | dd 0 15 | 16 | ; Set mxcsr regiter rouding bits 17 | %macro setRoundingBits 1 18 | stmxcsr [mxcsr] 19 | mov eax, [mxcsr] 20 | and ax, 0x9F80 21 | or ah, %1 22 | mov [mxcsr], eax 23 | ldmxcsr [mxcsr] 24 | %endmacro 25 | 26 | %include "header.inc" 27 | 28 | setRoundingBits 0x00 ; Round to nearest 29 | cvtps2pi mm0, [float0low] 30 | cvtps2pi mm4, [float1low] 31 | setRoundingBits 0x20 ; Round down 32 | cvtps2pi mm1, [float0low] 33 | cvtps2pi mm5, [float1low] 34 | setRoundingBits 0x40 ; Round up 35 | cvtps2pi mm2, [float0low] 36 | cvtps2pi mm6, [float1low] 37 | setRoundingBits 0x60 ; Round toward zero 38 | cvtps2pi mm3, [float0low] 39 | cvtps2pi mm7, [float1low] 40 | 41 | %include "footer.inc" 42 | -------------------------------------------------------------------------------- /tests/expect/readme.md: -------------------------------------------------------------------------------- 1 | Expect tests 2 | ------------ 3 | 4 | These so-called "expect tests" test the code generation, i.e. the translation 5 | of x86 assembly to Web Assembly. Use the following workflow: 6 | 7 | 1. Hack on the code generator 8 | 2. Run make `expect-tests` 9 | 3. For each failing test: 10 | - Manually verify that the generated code changes are as expected by the diff 11 | - If so, accept the new code by copying the .actual.wast file over the .wast file 12 | and checking the new .wast file into git 13 | 14 | In order to add a new expect test: 15 | 16 | 1. Create a new .asm file in tests/ 17 | 2. Run make `expect-tests` 18 | 3. Verify the generated code and use the printed cp command to accept the test 19 | 20 | Note that .asm files are translated to flat binaries, not elf files, so a .data 21 | section may be meaningless. 22 | 23 | 24 | For more information, see https://blog.janestreet.com/testing-with-expectations/ 25 | -------------------------------------------------------------------------------- /tools/docker/debian/build-container.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -veu 3 | 4 | IMAGES="$(dirname "$0")"/../../../images 5 | OUT_ROOTFS_TAR="$IMAGES"/debian-9p-rootfs.tar 6 | OUT_ROOTFS_FLAT="$IMAGES"/debian-9p-rootfs-flat 7 | OUT_FSJSON="$IMAGES"/debian-base-fs.json 8 | CONTAINER_NAME=debian-full 9 | IMAGE_NAME=i386/debian-full 10 | 11 | mkdir -p "$IMAGES" 12 | docker build . --platform linux/386 --rm --tag "$IMAGE_NAME" 13 | docker rm "$CONTAINER_NAME" || true 14 | docker create --platform linux/386 -t -i --name "$CONTAINER_NAME" "$IMAGE_NAME" bash 15 | 16 | docker export "$CONTAINER_NAME" > "$OUT_ROOTFS_TAR" 17 | 18 | "$(dirname "$0")"/../../../tools/fs2json.py --out "$OUT_FSJSON" "$OUT_ROOTFS_TAR" 19 | 20 | # Note: Not deleting old files here 21 | mkdir -p "$OUT_ROOTFS_FLAT" 22 | "$(dirname "$0")"/../../../tools/copy-to-sha256.py "$OUT_ROOTFS_TAR" "$OUT_ROOTFS_FLAT" 23 | 24 | echo "$OUT_ROOTFS_TAR", "$OUT_ROOTFS_FLAT" and "$OUT_FSJSON" created. 25 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/Makefile.x86_64: -------------------------------------------------------------------------------- 1 | cstart.o = $(TEST_DIR)/cstart64.o 2 | bits = 64 3 | ldarch = elf64-x86-64 4 | COMMON_CFLAGS += -mno-red-zone 5 | 6 | cflatobjs += lib/x86/setjmp64.o 7 | cflatobjs += lib/x86/intel-iommu.o 8 | 9 | tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \ 10 | $(TEST_DIR)/emulator.flat $(TEST_DIR)/idt_test.flat \ 11 | $(TEST_DIR)/xsave.flat $(TEST_DIR)/rmap_chain.flat \ 12 | $(TEST_DIR)/pcid.flat $(TEST_DIR)/debug.flat \ 13 | $(TEST_DIR)/ioapic.flat $(TEST_DIR)/memory.flat \ 14 | $(TEST_DIR)/pku.flat $(TEST_DIR)/hyperv_clock.flat 15 | tests += $(TEST_DIR)/syscall.flat 16 | tests += $(TEST_DIR)/svm.flat 17 | tests += $(TEST_DIR)/vmx.flat 18 | tests += $(TEST_DIR)/tscdeadline_latency.flat 19 | tests += $(TEST_DIR)/intel-iommu.flat 20 | 21 | include $(SRCDIR)/$(TEST_DIR)/Makefile.common 22 | 23 | $(TEST_DIR)/hyperv_clock.elf: $(TEST_DIR)/hyperv_clock.o 24 | 25 | $(TEST_DIR)/vmx.elf: $(TEST_DIR)/vmx_tests.o 26 | -------------------------------------------------------------------------------- /tests/nasm/maskmovdqu.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | 6 | dquad0: 7 | dq 0x1234567890abcdef 8 | dq 0xfedcba0987654321 9 | dquad1: 10 | dq 0xffffffffffffffff 11 | dq 0xffffffffffffffff 12 | mask0: 13 | dq 0x8081828384858687 14 | dq 0x88898a8b8c8d8e8f 15 | mask1: 16 | dq 0x10203080405080ff 17 | dq 0x1234567890abcdef 18 | 19 | %include "header.inc" 20 | 21 | movdqu xmm0, [dquad0] 22 | movdqu xmm1, [dquad1] 23 | movdqu xmm2, [dquad0] 24 | movdqu xmm3, [dquad1] 25 | movdqu xmm6, [mask0] 26 | movdqu xmm7, [mask1] 27 | 28 | ;; Look out for size of extracted memory region 29 | mov esp, stack_top - 16 30 | 31 | mov edi, esp 32 | maskmovdqu xmm0, xmm6 33 | sub esp, 16 34 | 35 | mov edi, esp 36 | maskmovdqu xmm1, xmm6 37 | sub esp, 16 38 | 39 | mov edi, esp 40 | maskmovdqu xmm2, xmm7 41 | sub esp, 16 42 | 43 | mov edi, esp 44 | maskmovdqu xmm3, xmm7 45 | sub esp, 16 46 | 47 | %include "footer.inc" 48 | -------------------------------------------------------------------------------- /src/rust/regs.rs: -------------------------------------------------------------------------------- 1 | pub const ES: u32 = 0; 2 | pub const CS: u32 = 1; 3 | pub const SS: u32 = 2; 4 | pub const DS: u32 = 3; 5 | pub const FS: u32 = 4; 6 | pub const GS: u32 = 5; 7 | 8 | pub const EAX: u32 = 0; 9 | pub const ECX: u32 = 1; 10 | pub const EDX: u32 = 2; 11 | pub const EBX: u32 = 3; 12 | pub const ESP: u32 = 4; 13 | pub const EBP: u32 = 5; 14 | pub const ESI: u32 = 6; 15 | pub const EDI: u32 = 7; 16 | 17 | pub const AX: u32 = 0; 18 | pub const CX: u32 = 1; 19 | pub const DX: u32 = 2; 20 | pub const BX: u32 = 3; 21 | pub const SP: u32 = 4; 22 | pub const BP: u32 = 5; 23 | pub const SI: u32 = 6; 24 | pub const DI: u32 = 7; 25 | 26 | pub const AL: u32 = 0; 27 | pub const CL: u32 = 1; 28 | pub const DL: u32 = 2; 29 | pub const BL: u32 = 3; 30 | pub const AH: u32 = 4; 31 | pub const CH: u32 = 5; 32 | pub const DH: u32 = 6; 33 | pub const BH: u32 = 7; 34 | 35 | pub const CR0_EM: u32 = 1 << 2; 36 | pub const CR0_TS: u32 = 1 << 3; 37 | 38 | pub const CR4_TSD: u32 = 1 << 2; 39 | -------------------------------------------------------------------------------- /tests/nasm/psllq.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | dq0: 6 | dq 0x0102030405060708 7 | dq 0xffffaaaabbbbcccc 8 | dq1: 9 | dq 0x8d0000ceadad00ff 10 | dq 0x0123456789abcdef 11 | mydword: 12 | dd 0xcafebac0 13 | 14 | align 16 15 | shift1: 16 | dq 0x07 17 | dq 0 18 | shift2: 19 | dq -0x22 20 | dq 0 21 | 22 | %include "header.inc" 23 | 24 | movq mm0, [dq0] 25 | movq mm1, [dq0] 26 | movq mm2, [dq0] 27 | movq mm3, [dq1] 28 | movq mm4, [dq1] 29 | movq mm6, [dq1] 30 | 31 | movq xmm0, [dq0] 32 | movq xmm1, [dq0] 33 | movq xmm2, [dq0] 34 | movq xmm3, [dq1] 35 | movq xmm4, [dq1] 36 | movq xmm6, [dq1] 37 | 38 | psllq mm0, [shift1] 39 | psllq mm1, [shift2] 40 | psllq mm2, 50 41 | psllq mm3, 28 42 | psllq mm4, 68 43 | psllq mm6, 0x5 44 | 45 | psllq xmm0, [shift1] 46 | psllq xmm1, [shift2] 47 | psllq xmm2, 50 48 | psllq xmm3, 28 49 | psllq xmm4, 68 50 | psllq xmm6, 0x5 51 | 52 | %include "footer.inc" 53 | 54 | -------------------------------------------------------------------------------- /docs/filesystem.md: -------------------------------------------------------------------------------- 1 | A 9p filesystem is supported by v86, using a virtio transport. Using 2 | it, files can be exchanged with the guest OS, see `create_file` and `read_file` 3 | in [`starter.js`](https://github.com/copy/v86/blob/master/src/browser/starter.js). 4 | It can be enabled by passing the following options to `V86`: 5 | 6 | ```javascript 7 | filesystem: { 8 | basefs: "../9p/fs.json", 9 | baseurl: "../9p/base/", 10 | } 11 | ``` 12 | 13 | Here, `basefs` is a json file created using 14 | [fs2json](https://github.com/copy/fs2json). The base url is the prefix of a url 15 | from which the files are available. For instance, if the 9p filesystem has a 16 | file `/bin/sh`, that file must be accessible from 17 | `http://localhost/9p/base/bin/sh`. If `basefs` and `baseurl` are omitted, an 18 | empty 9p filesystem is created. 19 | 20 | The `mount_tag` of the 9p device is `host9p`. In order to mount it in the 21 | guest, use: 22 | 23 | ```sh 24 | mount -t 9p host9p /mnt/9p/ 25 | ``` 26 | -------------------------------------------------------------------------------- /examples/destroy.html: -------------------------------------------------------------------------------- 1 | 2 | Destroyable Emulator 3 | 4 | 5 | 30 | 31 |
32 |
33 | 34 |
35 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/atomic.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "atomic.h" 3 | 4 | #ifdef __i386__ 5 | 6 | u64 atomic64_cmpxchg(atomic64_t *v, u64 old, u64 new) 7 | { 8 | u32 low = new; 9 | u32 high = new >> 32; 10 | 11 | asm volatile("lock cmpxchg8b %1\n" 12 | : "+A" (old), 13 | "+m" (*(volatile long long *)&v->counter) 14 | : "b" (low), "c" (high) 15 | : "memory" 16 | ); 17 | 18 | return old; 19 | } 20 | 21 | #else 22 | 23 | u64 atomic64_cmpxchg(atomic64_t *v, u64 old, u64 new) 24 | { 25 | u64 ret; 26 | u64 _old = old; 27 | u64 _new = new; 28 | 29 | asm volatile("lock cmpxchgq %2,%1" 30 | : "=a" (ret), "+m" (*(volatile long *)&v->counter) 31 | : "r" (_new), "0" (_old) 32 | : "memory" 33 | ); 34 | return ret; 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /tests/nasm/header.inc: -------------------------------------------------------------------------------- 1 | MBALIGN equ 1<<0 ; align loaded modules on page boundaries 2 | MEMINFO equ 1<<1 ; provide memory map 3 | FLAGS equ 0 ; this is the Multiboot 'flag' field 4 | MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader find the header 5 | CHECKSUM equ -(MAGIC + FLAGS) ; checksum of above, to prove we are multiboot 6 | section .multiboot 7 | align 4 8 | dd MAGIC 9 | dd FLAGS 10 | dd CHECKSUM 11 | 12 | section .bss 13 | resb 2*4096 ; 0x2000 14 | 15 | stack_top: 16 | 17 | section .text 18 | 19 | _start: 20 | main: 21 | xor eax, eax 22 | xor ecx, ecx 23 | xor edx, edx 24 | xor ebx, ebx 25 | mov esp, stack_top 26 | xor ebp, ebp 27 | xor esi, esi 28 | xor edi, edi 29 | 30 | pxor xmm0, xmm0 31 | 32 | ; make space for memory operations 33 | sub esp, 32 34 | 35 | push 0 36 | popf 37 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/string.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Header for libc string functions 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU Library General Public License version 2. 6 | */ 7 | #ifndef __STRING_H 8 | #define __STRING_H 9 | 10 | extern unsigned long strlen(const char *buf); 11 | extern char *strcat(char *dest, const char *src); 12 | extern char *strcpy(char *dest, const char *src); 13 | extern int strcmp(const char *a, const char *b); 14 | extern int strncmp(const char *a, const char *b, size_t n); 15 | extern char *strchr(const char *s, int c); 16 | extern char *strstr(const char *haystack, const char *needle); 17 | extern void *memset(void *s, int c, size_t n); 18 | extern void *memcpy(void *dest, const void *src, size_t n); 19 | extern int memcmp(const void *s1, const void *s2, size_t n); 20 | extern void *memmove(void *dest, const void *src, size_t n); 21 | extern void *memchr(const void *s, int c, size_t n); 22 | 23 | #endif /* _STRING_H */ 24 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/Makefile.i386: -------------------------------------------------------------------------------- 1 | cstart.o = $(TEST_DIR)/cstart.o 2 | bits = 32 3 | ldarch = elf32-i386 4 | 5 | cflatobjs += lib/x86/setjmp32.o 6 | 7 | tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat \ 8 | $(TEST_DIR)/cmpxchg8b.flat 9 | 10 | 11 | # added some tests from Makefile.x86_64 12 | tests += $(TEST_DIR)/apic.flat \ 13 | $(TEST_DIR)/rmap_chain.flat \ 14 | $(TEST_DIR)/ioapic.flat $(TEST_DIR)/memory.flat 15 | 16 | 17 | # These tests from Makefile.x86_64 don't compile. emulator.c would be nice to have 18 | # $(TEST_DIR)/emulator.flat 19 | # $(TEST_DIR)/access.flat 20 | # $(TEST_DIR)/idt_test.flat 21 | # $(TEST_DIR)/xsave.flat 22 | # $(TEST_DIR)/pcid.flat 23 | # $(TEST_DIR)/debug.flat 24 | # $(TEST_DIR)/pku.flat 25 | # $(TEST_DIR)/hyperv_clock.flat 26 | 27 | #tests += $(TEST_DIR)/svm.flat 28 | #tests += $(TEST_DIR)/vmx.flat 29 | tests += $(TEST_DIR)/tscdeadline_latency.flat 30 | #tests += $(TEST_DIR)/intel-iommu.flat 31 | 32 | 33 | include $(SRCDIR)/$(TEST_DIR)/Makefile.common 34 | -------------------------------------------------------------------------------- /tests/nasm/mov16.asm: -------------------------------------------------------------------------------- 1 | ;;; Test JIT optimization of opcodes 0x89 and 0x8b 2 | 3 | global _start 4 | 5 | section .data 6 | align 16 7 | mydword: 8 | dd 0xcafebabe 9 | myaddress: 10 | dd 0xdeadbeef 11 | 12 | %include "header.inc" 13 | 14 | ;; Load 32-bit values to confirm that the 16-bit movs do not overwrite existing values here 15 | mov eax, 0xcafeb055 16 | mov esi, 0x1bada551 17 | 18 | mov ecx, [mydword] 19 | mov edx, [myaddress] 20 | 21 | mov [myaddress], cx 22 | mov [mydword], dx 23 | 24 | ;; The following db's are used since mov reg, reg can be accomplished with several opcodes but 25 | ;; we want to test these specific ones 26 | 27 | ;; mov cx, si 28 | db 0x66 29 | db 0x89 30 | db 0xf1 31 | ;; mov dx, di 32 | db 0x66 33 | db 0x89 34 | db 0xfa 35 | 36 | ;; mov dx, ax 37 | db 0x66 38 | db 0x8b 39 | db 0xd0 40 | ;; mov ax, cx 41 | db 0x66 42 | db 0x8b 43 | db 0xc1 44 | 45 | %include "footer.inc" 46 | -------------------------------------------------------------------------------- /tests/nasm/psllw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | dq1: 6 | dq 0xad0000ceadad00ff 7 | dq 0xad0000ceadad00ff 8 | dq2: 9 | dq 0x42ff88ff11aabbcc 10 | dq 0x42ff88ff11aabbcc 11 | mydword: 12 | dd 0xcafebac0 13 | 14 | align 16 15 | shift1: 16 | dq 0x07 17 | dq 0 18 | shift2: 19 | dq -0x22 20 | dq 0 21 | shift3: 22 | dq 8 23 | dq 0 24 | 25 | %include "header.inc" 26 | 27 | movq mm0, [dq1] 28 | movq mm1, [dq1] 29 | movq mm2, [dq1] 30 | movq mm3, [dq2] 31 | movq mm4, [dq2] 32 | movq mm6, [dq2] 33 | 34 | movq xmm0, [dq1] 35 | movq xmm1, [dq1] 36 | movq xmm2, [dq1] 37 | movq xmm3, [dq2] 38 | movq xmm4, [dq2] 39 | movq xmm6, [dq2] 40 | 41 | psllw mm0, [shift1] 42 | psllw mm1, 0xff 43 | psllw mm2, [shift2] 44 | psllw mm3, 12 45 | psllw mm4, [shift3] 46 | psllw mm6, 0x5 47 | 48 | psllw xmm0, [shift1] 49 | psllw xmm1, 0xff 50 | psllw xmm2, [shift2] 51 | psllw xmm3, 12 52 | psllw xmm4, [shift3] 53 | psllw xmm6, 0x5 54 | 55 | %include "footer.inc" 56 | 57 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/api/memmap.hh: -------------------------------------------------------------------------------- 1 | #ifndef MEMMAP_HH 2 | #define MEMMAP_HH 3 | 4 | #include "kvmxx.hh" 5 | #include 6 | #include 7 | #include 8 | 9 | class mem_map; 10 | class mem_slot; 11 | 12 | class mem_slot { 13 | public: 14 | mem_slot(mem_map& map, uint64_t gpa, uint64_t size, void *hva); 15 | ~mem_slot(); 16 | void set_dirty_logging(bool enabled); 17 | bool dirty_logging() const; 18 | int update_dirty_log(); 19 | bool is_dirty(uint64_t gpa) const; 20 | private: 21 | void update(); 22 | private: 23 | typedef unsigned long ulong; 24 | static const int bits_per_word = sizeof(ulong) * 8; 25 | mem_map& _map; 26 | int _slot; 27 | uint64_t _gpa; 28 | uint64_t _size; 29 | void *_hva; 30 | bool _dirty_log_enabled; 31 | std::vector _log; 32 | }; 33 | 34 | class mem_map { 35 | public: 36 | mem_map(kvm::vm& vm); 37 | private: 38 | kvm::vm& _vm; 39 | std::stack _free_slots; 40 | friend class mem_slot; 41 | }; 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /examples/basic.html: -------------------------------------------------------------------------------- 1 | 2 | Basic Emulator 3 | 4 | 5 | 28 | 29 | 30 |
31 |
32 | 33 |
34 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/asm-generic/pci-host-bridge.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASM_PCI_HOST_BRIDGE_H_ 2 | #define _ASM_PCI_HOST_BRIDGE_H_ 3 | /* 4 | * Copyright (C) 2016, Red Hat Inc, Alexander Gordeev 5 | * 6 | * This work is licensed under the terms of the GNU LGPL, version 2. 7 | */ 8 | #include "libcflat.h" 9 | 10 | phys_addr_t pci_host_bridge_get_paddr(uint64_t addr); 11 | 12 | static inline 13 | phys_addr_t pci_translate_addr(pcidevaddr_t dev __unused, uint64_t addr) 14 | { 15 | /* 16 | * Assume we only have single PCI host bridge in a system. 17 | */ 18 | return pci_host_bridge_get_paddr(addr); 19 | } 20 | 21 | uint8_t pci_config_readb(pcidevaddr_t dev, uint8_t reg); 22 | uint16_t pci_config_readw(pcidevaddr_t dev, uint8_t reg); 23 | uint32_t pci_config_readl(pcidevaddr_t dev, uint8_t reg); 24 | void pci_config_writeb(pcidevaddr_t dev, uint8_t reg, uint8_t val); 25 | void pci_config_writew(pcidevaddr_t dev, uint8_t reg, uint16_t val); 26 | void pci_config_writel(pcidevaddr_t dev, uint8_t reg, uint32_t val); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/taskswitch.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010 Siemens AG 3 | * Author: Jan Kiszka 4 | * 5 | * Released under GPLv2. 6 | */ 7 | 8 | #include "libcflat.h" 9 | #include "x86/desc.h" 10 | 11 | #define TSS_RETURN (FIRST_SPARE_SEL) 12 | 13 | void fault_entry(void); 14 | 15 | static __attribute__((used, regparm(1))) void 16 | fault_handler(unsigned long error_code) 17 | { 18 | print_current_tss_info(); 19 | printf("error code %lx\n", error_code); 20 | 21 | tss.eip += 2; 22 | 23 | gdt32[TSS_MAIN / 8].access &= ~2; 24 | 25 | set_gdt_task_gate(TSS_RETURN, tss_intr.prev); 26 | } 27 | 28 | asm ( 29 | "fault_entry:\n" 30 | " mov (%esp),%eax\n" 31 | " call fault_handler\n" 32 | " jmp $" xstr(TSS_RETURN) ", $0\n" 33 | ); 34 | 35 | int main(int ac, char **av) 36 | { 37 | const long invalid_segment = 0x1234; 38 | 39 | setup_tss32(); 40 | set_intr_task_gate(13, fault_entry); 41 | 42 | asm ( 43 | "mov %0,%%es\n" 44 | : : "r" (invalid_segment) : "edi" 45 | ); 46 | 47 | printf("post fault\n"); 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/api/identity.hh: -------------------------------------------------------------------------------- 1 | #ifndef API_IDENTITY_HH 2 | #define API_IDENTITY_HH 3 | 4 | #include "kvmxx.hh" 5 | #include "memmap.hh" 6 | #include 7 | #include 8 | #include 9 | 10 | namespace identity { 11 | 12 | struct hole { 13 | hole(); 14 | hole(void* address, size_t size); 15 | void* address; 16 | size_t size; 17 | }; 18 | 19 | class vm { 20 | public: 21 | vm(kvm::vm& vm, mem_map& mmap, hole address_space_hole = hole()); 22 | ~vm(); 23 | private: 24 | void *tss; 25 | typedef std::shared_ptr mem_slot_ptr; 26 | std::vector _slots; 27 | }; 28 | 29 | class vcpu { 30 | public: 31 | vcpu(kvm::vcpu& vcpu, std::function guest_func, 32 | unsigned long stack_size = 256 * 1024); 33 | private: 34 | static void thunk(vcpu* vcpu); 35 | void setup_regs(); 36 | void setup_sregs(); 37 | private: 38 | kvm::vcpu& _vcpu; 39 | std::function _guest_func; 40 | std::vector _stack; 41 | }; 42 | 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/tsc.c: -------------------------------------------------------------------------------- 1 | #include "libcflat.h" 2 | #include "processor.h" 3 | 4 | #define CPUID_80000001_EDX_RDTSCP (1 << 27) 5 | int check_cpuid_80000001_edx(unsigned int bit) 6 | { 7 | return (cpuid(0x80000001).d & bit) != 0; 8 | } 9 | 10 | 11 | void test_wrtsc(u64 t1) 12 | { 13 | u64 t2; 14 | 15 | wrtsc(t1); 16 | t2 = rdtsc(); 17 | printf("rdtsc after wrtsc(%" PRId64 "): %" PRId64 "\n", t1, t2); 18 | } 19 | 20 | void test_rdtscp(u64 aux) 21 | { 22 | u32 ecx; 23 | 24 | wrmsr(MSR_TSC_AUX, aux); 25 | rdtscp(&ecx); 26 | report("Test RDTSCP %" PRIu64, ecx == aux, aux); 27 | } 28 | 29 | int main() 30 | { 31 | u64 t1, t2; 32 | 33 | t1 = rdtsc(); 34 | t2 = rdtsc(); 35 | printf("rdtsc latency %u\n", (unsigned)(t2 - t1)); 36 | 37 | test_wrtsc(0); 38 | test_wrtsc(100000000000ull); 39 | 40 | if (check_cpuid_80000001_edx(CPUID_80000001_EDX_RDTSCP)) { 41 | test_rdtscp(0); 42 | test_rdtscp(10); 43 | test_rdtscp(0x100); 44 | } else 45 | printf("rdtscp not supported\n"); 46 | return report_summary(); 47 | } 48 | -------------------------------------------------------------------------------- /tests/nasm/jump.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | 6 | %include "header.inc" 7 | 8 | mov eax, 0 9 | mov ebx, 0 10 | mov ecx, 0 11 | mov edx, 0 12 | mov esi, 0 13 | mov edi, 0 14 | 15 | ; skip 16 | jmp .target1 17 | inc eax 18 | .target1: 19 | 20 | ; conditional jump up 21 | .target2: 22 | inc ebx 23 | inc ecx 24 | cmp ebx, 2 25 | jne .target2 26 | 27 | ; conditional jump down 28 | .target3: 29 | cmp ebx, 4 30 | je .target4 31 | inc ebx 32 | inc edx 33 | jmp .target3 34 | 35 | .target4: 36 | call .fun 37 | call .not_returning_fun 38 | .after_call: 39 | jmp .after_fun 40 | 41 | .fun: 42 | inc esi 43 | ret 44 | 45 | .not_returning_fun: 46 | inc esi 47 | jmp .after_call 48 | inc esi 49 | ret 50 | 51 | .after_fun: 52 | push .target5 53 | ret 54 | .target5: 55 | 56 | ; clear stack (pushed eip is not the same between vm and gdb execution) 57 | mov dword [esp], 0 58 | mov dword [esp-4], 0 59 | 60 | %include "footer.inc" 61 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/asm-generic/atomic.h: -------------------------------------------------------------------------------- 1 | #ifndef __ASM_GENERIC_ATOMIC_H__ 2 | #define __ASM_GENERIC_ATOMIC_H__ 3 | 4 | /* From QEMU include/qemu/atomic.h */ 5 | #define atomic_fetch_inc(ptr) __sync_fetch_and_add(ptr, 1) 6 | #define atomic_fetch_dec(ptr) __sync_fetch_and_add(ptr, -1) 7 | #define atomic_fetch_add(ptr, n) __sync_fetch_and_add(ptr, n) 8 | #define atomic_fetch_sub(ptr, n) __sync_fetch_and_sub(ptr, n) 9 | #define atomic_fetch_and(ptr, n) __sync_fetch_and_and(ptr, n) 10 | #define atomic_fetch_or(ptr, n) __sync_fetch_and_or(ptr, n) 11 | #define atomic_fetch_xor(ptr, n) __sync_fetch_and_xor(ptr, n) 12 | 13 | #define atomic_inc_fetch(ptr) __sync_add_and_fetch(ptr, 1) 14 | #define atomic_dec_fetch(ptr) __sync_add_and_fetch(ptr, -1) 15 | #define atomic_add_fetch(ptr, n) __sync_add_and_fetch(ptr, n) 16 | #define atomic_sub_fetch(ptr, n) __sync_sub_and_fetch(ptr, n) 17 | #define atomic_and_fetch(ptr, n) __sync_and_and_fetch(ptr, n) 18 | #define atomic_or_fetch(ptr, n) __sync_or_and_fetch(ptr, n) 19 | #define atomic_xor_fetch(ptr, n) __sync_xor_and_fetch(ptr, n) 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/rust/state_flags.rs: -------------------------------------------------------------------------------- 1 | #[derive(Copy, Clone, PartialEq, Eq)] 2 | #[repr(transparent)] 3 | pub struct CachedStateFlags(u8); 4 | 5 | impl CachedStateFlags { 6 | const MASK_IS_32: u8 = 1 << 0; 7 | const MASK_SS32: u8 = 1 << 1; 8 | const MASK_CPL3: u8 = 1 << 2; 9 | const MASK_FLAT_SEGS: u8 = 1 << 3; 10 | 11 | pub const EMPTY: CachedStateFlags = CachedStateFlags(0); 12 | 13 | pub fn of_u32(f: u32) -> CachedStateFlags { 14 | dbg_assert!( 15 | f as u8 16 | & !(Self::MASK_IS_32 | Self::MASK_SS32 | Self::MASK_CPL3 | Self::MASK_FLAT_SEGS) 17 | == 0 18 | ); 19 | CachedStateFlags(f as u8) 20 | } 21 | pub fn to_u32(&self) -> u32 { self.0 as u32 } 22 | 23 | pub fn cpl3(&self) -> bool { self.0 & CachedStateFlags::MASK_CPL3 != 0 } 24 | pub fn has_flat_segmentation(&self) -> bool { self.0 & CachedStateFlags::MASK_FLAT_SEGS != 0 } 25 | pub fn is_32(&self) -> bool { self.0 & CachedStateFlags::MASK_IS_32 != 0 } 26 | pub fn ssize_32(&self) -> bool { self.0 & CachedStateFlags::MASK_SS32 != 0 } 27 | } 28 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/fwcfg.c: -------------------------------------------------------------------------------- 1 | #include "fwcfg.h" 2 | #include "smp.h" 3 | 4 | static struct spinlock lock; 5 | 6 | static uint64_t fwcfg_get_u(uint16_t index, int bytes) 7 | { 8 | uint64_t r = 0; 9 | uint8_t b; 10 | int i; 11 | 12 | spin_lock(&lock); 13 | asm volatile ("out %0, %1" : : "a"(index), "d"((uint16_t)BIOS_CFG_IOPORT)); 14 | for (i = 0; i < bytes; ++i) { 15 | asm volatile ("in %1, %0" : "=a"(b) : "d"((uint16_t)(BIOS_CFG_IOPORT + 1))); 16 | r |= (uint64_t)b << (i * 8); 17 | } 18 | spin_unlock(&lock); 19 | return r; 20 | } 21 | 22 | uint8_t fwcfg_get_u8(unsigned index) 23 | { 24 | return fwcfg_get_u(index, 1); 25 | } 26 | 27 | uint16_t fwcfg_get_u16(unsigned index) 28 | { 29 | return fwcfg_get_u(index, 2); 30 | } 31 | 32 | uint32_t fwcfg_get_u32(unsigned index) 33 | { 34 | return fwcfg_get_u(index, 4); 35 | } 36 | 37 | uint64_t fwcfg_get_u64(unsigned index) 38 | { 39 | return fwcfg_get_u(index, 8); 40 | } 41 | 42 | unsigned fwcfg_get_nb_cpus(void) 43 | { 44 | return fwcfg_get_u16(FW_CFG_NB_CPUS); 45 | } 46 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/idt_test.c: -------------------------------------------------------------------------------- 1 | #include "libcflat.h" 2 | #include "desc.h" 3 | 4 | int test_ud2(bool *rflags_rf) 5 | { 6 | asm volatile(ASM_TRY("1f") 7 | "ud2 \n\t" 8 | "1:" :); 9 | *rflags_rf = exception_rflags_rf(); 10 | return exception_vector(); 11 | } 12 | 13 | int test_gp(bool *rflags_rf) 14 | { 15 | unsigned long tmp; 16 | 17 | asm volatile("mov $0xffffffff, %0 \n\t" 18 | ASM_TRY("1f") 19 | "mov %0, %%cr4\n\t" 20 | "1:" 21 | : "=a"(tmp)); 22 | *rflags_rf = exception_rflags_rf(); 23 | return exception_vector(); 24 | } 25 | 26 | int main(void) 27 | { 28 | int r; 29 | bool rflags_rf; 30 | 31 | printf("Starting IDT test\n"); 32 | setup_idt(); 33 | r = test_gp(&rflags_rf); 34 | report("Testing #GP", r == GP_VECTOR); 35 | report("Testing #GP rflags.rf", rflags_rf); 36 | r = test_ud2(&rflags_rf); 37 | report("Testing #UD", r == UD_VECTOR); 38 | report("Testing #UD rflags.rf", rflags_rf); 39 | 40 | return report_summary(); 41 | } 42 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/sieve.c: -------------------------------------------------------------------------------- 1 | #include "vm.h" 2 | #include "libcflat.h" 3 | 4 | int sieve(char* data, int size) 5 | { 6 | int i, j, r = 0; 7 | 8 | for (i = 0; i < size; ++i) 9 | data[i] = 1; 10 | 11 | data[0] = data[1] = 0; 12 | 13 | for (i = 2; i < size; ++i) 14 | if (data[i]) { 15 | ++r; 16 | for (j = i*2; j < size; j += i) 17 | data[j] = 0; 18 | } 19 | return r; 20 | } 21 | 22 | void test_sieve(const char *msg, char *data, int size) 23 | { 24 | int r; 25 | 26 | printf("%s:", msg); 27 | r = sieve(data, size); 28 | printf("%d out of %d\n", r, size); 29 | } 30 | 31 | #define STATIC_SIZE 1000000 32 | #define VSIZE 2000000 33 | char static_data[STATIC_SIZE]; 34 | 35 | int main() 36 | { 37 | void *v; 38 | int i; 39 | 40 | printf("starting sieve\n"); 41 | test_sieve("static", static_data, STATIC_SIZE); 42 | setup_vm(); 43 | test_sieve("mapped", static_data, STATIC_SIZE); 44 | for (i = 0; i < 3; ++i) { 45 | v = vmalloc(VSIZE); 46 | test_sieve("virtual", v, VSIZE); 47 | vfree(v); 48 | } 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/kvmclock.h: -------------------------------------------------------------------------------- 1 | #ifndef KVMCLOCK_H 2 | #define KVMCLOCK_H 3 | 4 | #define MSR_KVM_WALL_CLOCK_NEW 0x4b564d00 5 | #define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01 6 | 7 | #define MAX_CPU 64 8 | 9 | #define PVCLOCK_TSC_STABLE_BIT (1 << 0) 10 | #define PVCLOCK_RAW_CYCLE_BIT (1 << 7) /* Get raw cycle */ 11 | 12 | # define NSEC_PER_SEC 1000000000ULL 13 | 14 | typedef u64 cycle_t; 15 | 16 | struct pvclock_vcpu_time_info { 17 | u32 version; 18 | u32 pad0; 19 | u64 tsc_timestamp; 20 | u64 system_time; 21 | u32 tsc_to_system_mul; 22 | s8 tsc_shift; 23 | u8 flags; 24 | u8 pad[2]; 25 | } __attribute__((__packed__)); /* 32 bytes */ 26 | 27 | struct pvclock_wall_clock { 28 | u32 version; 29 | u32 sec; 30 | u32 nsec; 31 | } __attribute__((__packed__)); 32 | 33 | struct timespec { 34 | long tv_sec; 35 | long tv_nsec; 36 | }; 37 | 38 | void pvclock_set_flags(unsigned char flags); 39 | cycle_t kvm_clock_read(); 40 | void kvm_get_wallclock(struct timespec *ts); 41 | void kvm_clock_init(void *data); 42 | void kvm_clock_clear(void *data); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /tests/rust/verify-wasmgen-dummy-output.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | process.on("unhandledRejection", exn => { throw exn; }); 5 | 6 | const assert = require("assert").strict; 7 | const fs = require("fs"); 8 | const path = require("path"); 9 | 10 | const DUMMY_MODULE_PATH = path.resolve(__dirname, "../../build/dummy_output.wasm"); 11 | const dummy_module = fs.readFileSync(DUMMY_MODULE_PATH); 12 | 13 | const wm = new WebAssembly.Module(dummy_module); 14 | const mem = new WebAssembly.Memory({ initial: 256 }); 15 | 16 | // These tests have to be kept in sync with src/rust/wasmgen/module_init.rs' tests 17 | // XXX: make the test more complex, involving locals, conditionals and stuff 18 | 19 | let baz_recd_arg; 20 | function baz(arg) { 21 | baz_recd_arg = arg; 22 | return 456; 23 | } 24 | 25 | let foo_recd_arg; 26 | function foo(arg) { 27 | foo_recd_arg = arg; 28 | } 29 | 30 | const i = new WebAssembly.Instance(wm, { "e": { m: mem, baz, foo } }); 31 | i.exports.f(); 32 | 33 | assert(baz_recd_arg === 2, `baz returned: "${baz_recd_arg}"`); 34 | assert(foo_recd_arg === 456, `foo returned: "${foo_recd_arg}"`); 35 | -------------------------------------------------------------------------------- /tests/nasm/psrlq.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | mydq0: 6 | dq 0xad0000ceadad00ff 7 | dq 0xff00dadaec0000da 8 | mydq1: 9 | dq 0x0102030405060708 10 | dq 0x090a0b0c0d0e0f10 11 | mydword: 12 | dd 0xcafebac0 13 | 14 | align 16 15 | shift0: 16 | dq 0x07 17 | dq 0 18 | shift1: 19 | dq -0x22 20 | dq 0 21 | 22 | %include "header.inc" 23 | 24 | movq mm0, [mydq0] 25 | movq mm1, [mydq0] 26 | movq mm2, [mydq0] 27 | movq mm3, [mydq1] 28 | movq mm4, [mydq1] 29 | movq mm6, [mydq1] 30 | 31 | movq xmm0, [mydq0] 32 | movq xmm1, [mydq0] 33 | movq xmm2, [mydq0] 34 | movq xmm3, [mydq1] 35 | movq xmm4, [mydq1] 36 | movq xmm6, [mydq1] 37 | 38 | psrlq mm0, [shift1] 39 | psrlq mm1, [shift0] 40 | psrlq mm2, 0x65 41 | psrlq mm3, 0x25 42 | psrlq mm4, 0x1F 43 | psrlq mm6, 0x5 44 | 45 | movq xmm0, [mydq0] 46 | movq xmm1, [mydq0] 47 | movq xmm2, [mydq1] 48 | movq xmm3, [mydq1] 49 | movq xmm6, [mydq1] 50 | 51 | psrlq xmm0, [shift1] 52 | psrlq xmm1, [shift0] 53 | psrlq xmm2, 0x65 54 | psrlq xmm3, 0x25 55 | psrlq xmm4, 0x1F 56 | psrlq xmm6, 0x5 57 | 58 | %include "footer.inc" 59 | -------------------------------------------------------------------------------- /examples/nodejs.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | var fs = require("fs"); 5 | var V86 = require("../build/libv86.js").V86; 6 | 7 | function readfile(path) 8 | { 9 | return new Uint8Array(fs.readFileSync(path)).buffer; 10 | } 11 | 12 | var bios = readfile(__dirname + "/../bios/seabios.bin"); 13 | var linux = readfile(__dirname + "/../images/linux4.iso"); 14 | 15 | process.stdin.setRawMode(true); 16 | process.stdin.resume(); 17 | process.stdin.setEncoding("utf8"); 18 | 19 | console.log("Now booting, please stand by ..."); 20 | 21 | var emulator = new V86({ 22 | bios: { buffer: bios }, 23 | cdrom: { buffer: linux }, 24 | autostart: true, 25 | }); 26 | 27 | emulator.add_listener("serial0-output-byte", function(byte) 28 | { 29 | var chr = String.fromCharCode(byte); 30 | if(chr <= "~") 31 | { 32 | process.stdout.write(chr); 33 | } 34 | }); 35 | 36 | process.stdin.on("data", function(c) 37 | { 38 | if(c === "\u0003") 39 | { 40 | // ctrl c 41 | emulator.stop(); 42 | process.stdin.pause(); 43 | } 44 | else 45 | { 46 | emulator.serial0_send(c); 47 | } 48 | }); 49 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/errata.h: -------------------------------------------------------------------------------- 1 | /* 2 | * errata functions 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU Library General Public License version 2. 6 | */ 7 | #ifndef _ERRATA_H_ 8 | #define _ERRATA_H_ 9 | 10 | #define _ERRATA(erratum) errata("ERRATA_" # erratum) 11 | #define ERRATA(erratum) _ERRATA(erratum) 12 | 13 | #define _ERRATA_RELAXED(erratum) errata_relaxed("ERRATA_" # erratum) 14 | #define ERRATA_RELAXED(erratum) _ERRATA_RELAXED(erratum) 15 | 16 | static inline bool errata_force(void) 17 | { 18 | char *s = getenv("ERRATA_FORCE"); 19 | 20 | return s && (*s == '1' || *s == 'y' || *s == 'Y'); 21 | } 22 | 23 | static inline bool errata(const char *erratum) 24 | { 25 | char *s; 26 | 27 | if (errata_force()) 28 | return true; 29 | 30 | s = getenv(erratum); 31 | 32 | return s && (*s == '1' || *s == 'y' || *s == 'Y'); 33 | } 34 | 35 | static inline bool errata_relaxed(const char *erratum) 36 | { 37 | char *s; 38 | 39 | if (errata_force()) 40 | return true; 41 | 42 | s = getenv(erratum); 43 | 44 | return !(s && (*s == '0' || *s == 'n' || *s == 'N')); 45 | } 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /tools/docker/debian/Readme.md: -------------------------------------------------------------------------------- 1 | You can build a Linux image for use with v86: 2 | 3 | 1. Run `./build-container.sh` to build the Docker container and v86 images (requires dockerd) 4 | 2. Run `./build-state.js` to build a state image in order to skip the boot process 5 | 3. Optionally, compress the `debian-state-base.bin` file using zstd (v86 automatically detects the zstd magic and decompresses on the fly) 6 | 4. Run a webserver serving repo root and go to `examples/debian.html` in a browser 7 | 8 | If you want to see more info you can run it in a debug mode, to do so add a new profile in the `src/browser/main.js` file to the `oses` variable like so: 9 | 10 | ```js 11 | var oses = [ 12 | { 13 | id: "debian", 14 | name: "Debian", 15 | memory_size: 512 * 1024 * 1024, 16 | vga_memory_size: 8 * 1024 * 1024, 17 | state: { url: host + "debian-state-base.bin" }, 18 | filesystem: { baseurl: host + "debian-9p-rootfs-flat/" } 19 | }, 20 | ... 21 | ``` 22 | 23 | Save it and go to `debug.html?profile=debian` to start the generated container. 24 | 25 | You can modify the `Dockerfile` to customize the generated Linux image. 26 | -------------------------------------------------------------------------------- /tests/api/clean-shutdown.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | // This test checks that calling emulator.stop() will remove all event 5 | // listeners, so that the nodejs process cleanly and automatically exits. 6 | 7 | const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD; 8 | 9 | const fs = require("fs"); 10 | var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86; 11 | 12 | process.on("unhandledRejection", exn => { throw exn; }); 13 | 14 | const config = { 15 | bios: { url: __dirname + "/../../bios/seabios.bin" }, 16 | vga_bios: { url: __dirname + "/../../bios/vgabios.bin" }, 17 | cdrom: { url: __dirname + "/../../images/linux4.iso", async: true }, 18 | network_relay_url: "", 19 | autostart: true, 20 | memory_size: 32 * 1024 * 1024, 21 | filesystem: {}, 22 | log_level: 0, 23 | disable_jit: +process.env.DISABLE_JIT, 24 | screen_dummy: true, 25 | }; 26 | 27 | const emulator = new V86(config); 28 | 29 | setTimeout(function() 30 | { 31 | console.error("Calling stop()"); 32 | emulator.stop(); 33 | console.error("Called stop()"); 34 | }, 3000); 35 | -------------------------------------------------------------------------------- /tools/docker/debian/logind.conf: -------------------------------------------------------------------------------- 1 | # This file is part of systemd. 2 | # 3 | # systemd is free software; you can redistribute it and/or modify it 4 | # under the terms of the GNU Lesser General Public License as published by 5 | # the Free Software Foundation; either version 2.1 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # Entries in this file show the compile time defaults. 9 | # You can change settings by editing this file. 10 | # Defaults can be restored by simply deleting this file. 11 | # 12 | # See logind.conf(5) for details. 13 | 14 | [Login] 15 | NAutoVTs=0 16 | ReserveVT=0 17 | #KillUserProcesses=no 18 | #KillOnlyUsers= 19 | #KillExcludeUsers=root 20 | #InhibitDelayMaxSec=5 21 | #HandlePowerKey=poweroff 22 | #HandleSuspendKey=suspend 23 | #HandleHibernateKey=hibernate 24 | #HandleLidSwitch=suspend 25 | #HandleLidSwitchDocked=ignore 26 | #PowerKeyIgnoreInhibited=no 27 | #SuspendKeyIgnoreInhibited=no 28 | #HibernateKeyIgnoreInhibited=no 29 | #LidSwitchIgnoreInhibited=yes 30 | #HoldoffTimeoutSec=30s 31 | #IdleAction=ignore 32 | #IdleActionSec=30min 33 | #RuntimeDirectorySize=10% 34 | #RemoveIPC=yes 35 | #InhibitorsMax=8192 36 | #SessionsMax=8192 37 | #UserTasksMax=33% 38 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/bitops.h: -------------------------------------------------------------------------------- 1 | #ifndef _BITOPS_H_ 2 | #define _BITOPS_H_ 3 | 4 | /* 5 | * Adapted from 6 | * include/linux/bitops.h 7 | * 8 | * Copyright (C) 2017, Red Hat Inc, Andrew Jones 9 | * 10 | * This work is licensed under the terms of the GNU GPL, version 2. 11 | */ 12 | 13 | #define BITS_PER_LONG_LONG 64 14 | #define BIT(nr) (1UL << (nr)) 15 | #define BIT_ULL(nr) (1ULL << (nr)) 16 | #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) 17 | #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) 18 | #define BIT_ULL_MASK(nr) (1ULL << ((nr) % BITS_PER_LONG_LONG)) 19 | #define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG) 20 | #define BITS_PER_BYTE 8 21 | #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) 22 | 23 | #include 24 | 25 | /* 26 | * Create a contiguous bitmask starting at bit position @l and ending at 27 | * position @h. For example 28 | * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000. 29 | */ 30 | #define GENMASK(h, l) \ 31 | (((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) 32 | 33 | #define GENMASK_ULL(h, l) \ 34 | (((~0ULL) << (l)) & (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h)))) 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /tests/nasm/comiss.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | controlword: 6 | dw 0 7 | dwordmxcsr: 8 | dw 0 9 | dword0: 10 | dd 1000.0 11 | dword1: 12 | dd 5.0 13 | dword2: 14 | dd 3000.0 15 | dwSNaN: 16 | dd __SNaN__ 17 | dwQNaN: 18 | dd __QNaN__ 19 | 20 | ; Moves EFLAGS into specified register 21 | %macro moveflags 1 22 | pushf 23 | and dword [esp], 0x45 24 | pop eax 25 | movd %1, eax 26 | %endmacro 27 | 28 | %include "header.inc" 29 | 30 | movd xmm0, [dword0] 31 | ; Equal 32 | comiss xmm0, [dword0] 33 | moveflags mm0 ; [ZF] = 100000 34 | ; Less than 35 | comiss xmm0, [dword1] 36 | moveflags mm1 ; [CF] = 000001 37 | ; Greater than 38 | comiss xmm0, [dword2] 39 | moveflags mm2 ; [] = 000000 40 | 41 | ; Unordered: Quiet NaN 42 | movd xmm1, [dwQNaN] 43 | ucomiss xmm0, xmm1 44 | moveflags mm3 ; [ZF][PF][CF] = 100101 45 | ; Check #I exception 46 | stmxcsr [dwordmxcsr] 47 | movd mm4, [dwordmxcsr] 48 | 49 | ; Unordered: Signaling NaN 50 | movd xmm1,[dwSNaN] 51 | ucomiss xmm0, xmm1 52 | moveflags mm5 ; [ZF][PF][CF] = 100101 53 | ; Check #I exception 54 | stmxcsr [dwordmxcsr] 55 | movd mm6, [dwordmxcsr] 56 | 57 | %include "footer.inc" 58 | -------------------------------------------------------------------------------- /tests/nasm/ucomiss.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | controlword: 6 | dw 0 7 | dwordmxcsr: 8 | dw 0 9 | dword0: 10 | dd 1000.0 11 | dword1: 12 | dd 5.0 13 | dword2: 14 | dd 3000.0 15 | dwSNaN: 16 | dd __SNaN__ 17 | dwQNaN: 18 | dd __QNaN__ 19 | 20 | ; Moves EFLAGS into specified register 21 | %macro moveflags 1 22 | pushf 23 | and dword [esp], 0x45 24 | pop eax 25 | movd %1, eax 26 | %endmacro 27 | 28 | %include "header.inc" 29 | 30 | movd xmm0, [dword0] 31 | ; Equal 32 | ucomiss xmm0, [dword0] 33 | moveflags mm0 ; [ZF] = 100000 34 | ; Less than 35 | ucomiss xmm0, [dword1] 36 | moveflags mm1 ; [CF] = 000001 37 | ; Greater than 38 | ucomiss xmm0, [dword2] 39 | moveflags mm2 ; [] = 000000 40 | 41 | ; Unordered: Quiet NaN 42 | movd xmm1, [dwQNaN] 43 | ucomiss xmm0, xmm1 44 | moveflags mm3 ; [ZF][PF][CF] = 100101 45 | ; Check #I exception 46 | stmxcsr [dwordmxcsr] 47 | movd mm4, [dwordmxcsr] 48 | 49 | ; Unordered: Signaling NaN 50 | movd xmm1, [dwSNaN] 51 | ucomiss xmm0, xmm1 52 | moveflags mm5 ; [ZF][PF][CF] = 100101 53 | ; Check #I exception 54 | stmxcsr [dwordmxcsr] 55 | movd mm6, [dwordmxcsr] 56 | 57 | %include "footer.inc" 58 | -------------------------------------------------------------------------------- /tests/manual/gc.html: -------------------------------------------------------------------------------- 1 | 2 | Test that emulator is GCed properly 3 | 4 | 5 | 28 | 29 | 30 |
31 |
32 | 33 |
34 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/setup.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Initialize machine setup information 3 | * 4 | * Copyright (C) 2017, Red Hat Inc, Andrew Jones 5 | * 6 | * This work is licensed under the terms of the GNU LGPL, version 2. 7 | */ 8 | #include "libcflat.h" 9 | 10 | #define MBI_MODS_COUNT 20 11 | #define MBI_MODS_ADDR 24 12 | #define MB_MOD_START 0 13 | #define MB_MOD_END 4 14 | 15 | #define ENV_SIZE 16384 16 | 17 | extern void setup_env(char *env, int size); 18 | 19 | char *initrd; 20 | u32 initrd_size; 21 | 22 | static char env[ENV_SIZE]; 23 | 24 | void setup_get_initrd(u8 *bootinfo) 25 | { 26 | u32 *mods_addr, *mod_start, *mod_end; 27 | 28 | if (*((u32 *)&bootinfo[MBI_MODS_COUNT]) != 1) 29 | return; 30 | 31 | mods_addr = (u32 *)&bootinfo[MBI_MODS_ADDR]; 32 | mod_start = (u32 *)(ulong)(*mods_addr + MB_MOD_START); 33 | mod_end = (u32 *)(ulong)(*mods_addr + MB_MOD_END); 34 | 35 | initrd = (char *)(ulong)*mod_start; 36 | initrd_size = *mod_end - *mod_start; 37 | } 38 | 39 | void setup_environ(void) 40 | { 41 | if (initrd) { 42 | /* environ is currently the only file in the initrd */ 43 | u32 size = MIN(initrd_size, ENV_SIZE); 44 | memcpy(env, initrd, size); 45 | setup_env(env, size); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/rmap_chain.c: -------------------------------------------------------------------------------- 1 | /* test long rmap chains */ 2 | 3 | #include "libcflat.h" 4 | #include "fwcfg.h" 5 | #include "vm.h" 6 | #include "smp.h" 7 | 8 | int main (void) 9 | { 10 | int i; 11 | int nr_pages; 12 | void *target_page, *virt_addr; 13 | 14 | setup_vm(); 15 | 16 | nr_pages = fwcfg_get_u64(FW_CFG_RAM_SIZE) / PAGE_SIZE; 17 | nr_pages -= 1000; 18 | target_page = alloc_page(); 19 | 20 | virt_addr = (void *) 0xfffffa000; 21 | for (i = 0; i < nr_pages; i++) { 22 | install_page(phys_to_virt(read_cr3()), virt_to_phys(target_page), 23 | virt_addr); 24 | virt_addr += PAGE_SIZE; 25 | } 26 | printf("created %d mappings\n", nr_pages); 27 | 28 | virt_addr = (void *) 0xfffffa000; 29 | for (i = 0; i < nr_pages; i++) { 30 | unsigned long *touch = virt_addr; 31 | 32 | *touch = 0; 33 | virt_addr += PAGE_SIZE; 34 | } 35 | printf("instantiated mappings\n"); 36 | 37 | virt_addr += PAGE_SIZE; 38 | install_pte(phys_to_virt(read_cr3()), 1, virt_addr, 39 | 0 | PT_PRESENT_MASK | PT_WRITABLE_MASK, target_page); 40 | 41 | *(unsigned long *)virt_addr = 0; 42 | printf("PASS\n"); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | * Compile time configuration, some only relevant for debug mode 4 | */ 5 | 6 | /** 7 | * @define {boolean} 8 | * Overridden for production by closure compiler 9 | */ 10 | var DEBUG = true; 11 | 12 | /** @const */ 13 | var LOG_TO_FILE = false; 14 | 15 | /** 16 | * @const 17 | * Enables logging all IO port reads and writes. Very verbose 18 | */ 19 | var LOG_ALL_IO = false; 20 | 21 | /** 22 | * @const 23 | */ 24 | var DUMP_GENERATED_WASM = false; 25 | 26 | /** 27 | * @const 28 | */ 29 | var DUMP_UNCOMPILED_ASSEMBLY = false; 30 | 31 | /** 32 | * @const 33 | * More accurate filenames in 9p debug messages at the cost of performance. 34 | */ 35 | var TRACK_FILENAMES = false; 36 | 37 | var LOG_LEVEL = LOG_ALL & ~LOG_PS2 & ~LOG_PIT & ~LOG_VIRTIO & ~LOG_9P & ~LOG_PIC & 38 | ~LOG_DMA & ~LOG_SERIAL & ~LOG_NET & ~LOG_FLOPPY & ~LOG_DISK & ~LOG_VGA & ~LOG_SB16; 39 | 40 | /** 41 | * @const 42 | * Draws entire buffer and visualizes the layers that would be drawn 43 | */ 44 | var DEBUG_SCREEN_LAYERS = DEBUG && false; 45 | 46 | /** 47 | * @const 48 | * How many ticks the TSC does per millisecond 49 | */ 50 | var TSC_RATE = 1 * 1000 * 1000; 51 | 52 | /** @const */ 53 | var APIC_TIMER_FREQ = TSC_RATE; 54 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/tsc_adjust.c: -------------------------------------------------------------------------------- 1 | #include "libcflat.h" 2 | #include "processor.h" 3 | 4 | #define IA32_TSC_ADJUST 0x3b 5 | 6 | int main() 7 | { 8 | u64 t1, t2, t3, t4, t5; 9 | u64 est_delta_time; 10 | 11 | if (cpuid(7).b & (1 << 1)) { // IA32_TSC_ADJUST Feature is enabled? 12 | report("IA32_TSC_ADJUST msr initialization", 13 | rdmsr(IA32_TSC_ADJUST) == 0x0); 14 | t3 = 100000000000ull; 15 | t1 = rdtsc(); 16 | wrmsr(IA32_TSC_ADJUST, t3); 17 | t2 = rdtsc(); 18 | report("IA32_TSC_ADJUST msr read / write", 19 | rdmsr(IA32_TSC_ADJUST) == t3); 20 | report("TSC adjustment for IA32_TSC_ADJUST value", 21 | (t2 - t1) >= t3); 22 | t3 = 0x0; 23 | wrmsr(IA32_TSC_ADJUST, t3); 24 | report("IA32_TSC_ADJUST msr read / write", 25 | rdmsr(IA32_TSC_ADJUST) == t3); 26 | t4 = 100000000000ull; 27 | t1 = rdtsc(); 28 | wrtsc(t4); 29 | t2 = rdtsc(); 30 | t5 = rdmsr(IA32_TSC_ADJUST); 31 | // est of time between reading tsc and writing tsc, 32 | // (based on IA32_TSC_ADJUST msr value) should be small 33 | est_delta_time = t4 - t5 - t1; 34 | // arbitray 2x latency (wrtsc->rdtsc) threshold 35 | report("IA32_TSC_ADJUST msr adjustment on tsc write", 36 | est_delta_time <= (2 * (t2 - t4))); 37 | } 38 | else { 39 | report("IA32_TSC_ADJUST feature not enabled", true); 40 | } 41 | return report_summary(); 42 | } 43 | -------------------------------------------------------------------------------- /gen/util.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const fs = require("fs"); 5 | const path = require("path"); 6 | const process = require("process"); 7 | const child_process = require("child_process"); 8 | 9 | const CYAN_FMT = "\x1b[36m%s\x1b[0m"; 10 | 11 | function hex(n, pad) 12 | { 13 | pad = pad || 0; 14 | let s = n.toString(16).toUpperCase(); 15 | while(s.length < pad) s = "0" + s; 16 | return s; 17 | } 18 | 19 | function mkdirpSync(dir) 20 | { 21 | fs.mkdirSync(dir, { recursive: true }); 22 | } 23 | 24 | function get_switch_value(arg_switch) 25 | { 26 | const argv = process.argv; 27 | const switch_i = argv.indexOf(arg_switch); 28 | const val_i = switch_i + 1; 29 | if(switch_i > -1 && val_i < argv.length) 30 | { 31 | return argv[switch_i + 1]; 32 | } 33 | return null; 34 | } 35 | 36 | function get_switch_exist(arg_switch) 37 | { 38 | return process.argv.includes(arg_switch); 39 | } 40 | 41 | function finalize_table_rust(out_dir, name, contents) 42 | { 43 | const file_path = path.join(out_dir, name); 44 | fs.writeFileSync(file_path, contents); 45 | console.log(CYAN_FMT, `[+] Wrote table ${name}.`); 46 | } 47 | 48 | module.exports = { 49 | hex, 50 | mkdirpSync, 51 | get_switch_value, 52 | get_switch_exist, 53 | finalize_table_rust, 54 | }; 55 | -------------------------------------------------------------------------------- /tests/api/floppy-insert-eject.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD; 5 | 6 | const fs = require("fs"); 7 | var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86; 8 | 9 | process.on("unhandledRejection", exn => { throw exn; }); 10 | 11 | const emulator = new V86({ 12 | bios: { url: __dirname + "/../../bios/seabios.bin" }, 13 | vga_bios: { url: __dirname + "/../../bios/vgabios.bin" }, 14 | hda: { url: __dirname + "/../../images/msdos.img" }, 15 | network_relay_url: "", 16 | autostart: true, 17 | memory_size: 32 * 1024 * 1024, 18 | filesystem: {}, 19 | log_level: 0, 20 | disable_jit: +process.env.DISABLE_JIT, 21 | screen_dummy: true, 22 | }); 23 | 24 | emulator.automatically([ 25 | { sleep: 1 }, 26 | { vga_text: "C:\\> " }, 27 | { keyboard_send: "dir A:\n" }, 28 | { vga_text: "Abort, Retry, Fail?" }, 29 | { keyboard_send: "F" }, 30 | { call: () => { 31 | emulator.set_fda({ url: __dirname + "/../../images/freedos722.img" }); 32 | }, 33 | }, 34 | { keyboard_send: "dir A:\n" }, 35 | { sleep: 1 }, 36 | { vga_text: "FDOS " }, 37 | { call: () => { 38 | console.log("Passed"); 39 | emulator.stop(); 40 | } 41 | }, 42 | ]); 43 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/apic.h: -------------------------------------------------------------------------------- 1 | #ifndef CFLAT_APIC_H 2 | #define CFLAT_APIC_H 3 | 4 | #include 5 | #include "apic-defs.h" 6 | 7 | typedef struct { 8 | uint8_t vector; 9 | uint8_t delivery_mode:3; 10 | uint8_t dest_mode:1; 11 | uint8_t delivery_status:1; 12 | uint8_t polarity:1; 13 | uint8_t remote_irr:1; 14 | uint8_t trig_mode:1; 15 | uint8_t mask:1; 16 | uint8_t reserve:7; 17 | uint8_t reserved[4]; 18 | uint8_t dest_id; 19 | } ioapic_redir_entry_t; 20 | 21 | typedef enum trigger_mode { 22 | TRIGGER_EDGE = 0, 23 | TRIGGER_LEVEL, 24 | TRIGGER_MAX, 25 | } trigger_mode_t; 26 | 27 | void mask_pic_interrupts(void); 28 | 29 | void eoi(void); 30 | uint8_t apic_get_tpr(void); 31 | void apic_set_tpr(uint8_t tpr); 32 | 33 | void ioapic_write_redir(unsigned line, ioapic_redir_entry_t e); 34 | void ioapic_write_reg(unsigned reg, uint32_t value); 35 | ioapic_redir_entry_t ioapic_read_redir(unsigned line); 36 | uint32_t ioapic_read_reg(unsigned reg); 37 | 38 | void set_mask(unsigned line, int mask); 39 | 40 | void enable_apic(void); 41 | uint32_t apic_read(unsigned reg); 42 | bool apic_read_bit(unsigned reg, int n); 43 | void apic_write(unsigned reg, uint32_t val); 44 | void apic_icr_write(uint32_t val, uint32_t dest); 45 | uint32_t apic_id(void); 46 | 47 | int enable_x2apic(void); 48 | void reset_apic(void); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012, The v86 contributors 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /examples/async_load.html: -------------------------------------------------------------------------------- 1 | 2 | Asynchronous loading of disk images 3 | 4 | 5 | 39 | 40 |
41 |
42 | 43 |
44 | -------------------------------------------------------------------------------- /tests/Readme.md: -------------------------------------------------------------------------------- 1 | Use the corresponding `make` target in the root directory to run a test. The 2 | following list is roughtly sorted from most interesting/useful to least. 3 | 4 | - [nasm](nasm/): Small unit tests written in assembly, which are run using gdb 5 | on the host. 6 | - [qemu](qemu/): Based on tests from qemu. Builds a Linux binary, which tests 7 | many CPU features, which are then compared to a run on qemu. 8 | - [kvm-unit-test](kvm-unit-test/): Based on tests from the KVM project, tests 9 | various CPU features. 10 | - [full](full/): Starts several OSes and checks if they boot correctly. 11 | - [jit-paging](jit-paging/): Tests jit and paging interaction. 12 | - [api](api/): Tests for several API functions of v86. 13 | - [devices](devices/): Device tests. 14 | - [rust](rust/): Rust unit test helpers. 15 | - [expect](expect/): Expect tests for the jit output. Contains a set of 16 | asm+wasm files, where the jit is expected to produce the wasm file given the 17 | asm file. 18 | 19 | The following environmental variables are respected by most tests if applicable: 20 | 21 | - `TEST_RELEASE_BUILD=1`: Test the release build (libv86.js, v86.wasm) instead of the 22 | debug build (libv86-debug.js, v86-debug.wasm) 23 | - `MAX_PARALLEL_TESTS=n`: Maximum number of tests to run in parallel. Defaults 24 | to the number of cores in your system or less. 25 | - `TEST_NAME="…"`: Run only the specified test (only expect, full, nasm) 26 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/pci-host-generic.h: -------------------------------------------------------------------------------- 1 | #ifndef PCI_HOST_GENERIC_H 2 | #define PCI_HOST_GENERIC_H 3 | /* 4 | * PCI host bridge supporting structures and constants 5 | * 6 | * Copyright (C) 2016, Red Hat Inc, Alexander Gordeev 7 | * 8 | * This work is licensed under the terms of the GNU LGPL, version 2. 9 | */ 10 | #include "libcflat.h" 11 | 12 | struct pci_addr_space { 13 | phys_addr_t pci_start; 14 | phys_addr_t start; 15 | phys_addr_t size; 16 | phys_addr_t allocated; 17 | int type; 18 | }; 19 | 20 | struct pci_host_bridge { 21 | phys_addr_t start; 22 | phys_addr_t size; 23 | int bus; 24 | int bus_max; 25 | int nr_addr_spaces; 26 | struct pci_addr_space addr_space[]; 27 | }; 28 | 29 | /* 30 | * The following constants are derived from Linux, see this source: 31 | * 32 | * drivers/pci/host/pci-host-generic.c 33 | * struct gen_pci_cfg_bus_ops::bus_shift 34 | * int gen_pci_parse_map_cfg_windows(struct gen_pci *pci) 35 | * 36 | * Documentation/devicetree/bindings/pci/host-generic-pci.txt describes 37 | * ECAM Configuration Space is be memory-mapped by concatenating the various 38 | * components to form an offset: 39 | * 40 | * cfg_offset(bus, device, function, register) = 41 | * bus << 20 | device << 15 | function << 12 | register 42 | */ 43 | #define PCI_ECAM_BUS_SHIFT 20 44 | #define PCI_ECAM_DEVFN_SHIFT 12 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/asm/page.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASM_X86_PAGE_H_ 2 | #define _ASM_X86_PAGE_H_ 3 | /* 4 | * Copyright (C) 2016, Red Hat Inc, Alexander Gordeev 5 | * 6 | * This work is licensed under the terms of the GNU LGPL, version 2. 7 | */ 8 | 9 | 10 | #include 11 | #include 12 | 13 | #define PAGE_SHIFT 12 14 | #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) 15 | #define PAGE_MASK (~(PAGE_SIZE-1)) 16 | 17 | #ifndef __ASSEMBLY__ 18 | 19 | #ifdef __x86_64__ 20 | #define LARGE_PAGE_SIZE (512 * PAGE_SIZE) 21 | #else 22 | #define LARGE_PAGE_SIZE (1024 * PAGE_SIZE) 23 | #endif 24 | 25 | #define PT_PRESENT_MASK (1ull << 0) 26 | #define PT_WRITABLE_MASK (1ull << 1) 27 | #define PT_USER_MASK (1ull << 2) 28 | #define PT_ACCESSED_MASK (1ull << 5) 29 | #define PT_DIRTY_MASK (1ull << 6) 30 | #define PT_PAGE_SIZE_MASK (1ull << 7) 31 | #define PT64_NX_MASK (1ull << 63) 32 | #define PT_ADDR_MASK GENMASK_ULL(51, 12) 33 | 34 | #define PT_AD_MASK (PT_ACCESSED_MASK | PT_DIRTY_MASK) 35 | 36 | #ifdef __x86_64__ 37 | #define PAGE_LEVEL 4 38 | #define PGDIR_WIDTH 9 39 | #define PGDIR_MASK 511 40 | #else 41 | #define PAGE_LEVEL 2 42 | #define PGDIR_WIDTH 10 43 | #define PGDIR_MASK 1023 44 | #endif 45 | 46 | #define PGDIR_BITS(lvl) (((lvl) - 1) * PGDIR_WIDTH + PAGE_SHIFT) 47 | #define PGDIR_OFFSET(va, lvl) (((va) >> PGDIR_BITS(lvl)) & PGDIR_MASK) 48 | 49 | #endif /* !__ASSEMBLY__ */ 50 | #endif 51 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/libfdt/version.lds: -------------------------------------------------------------------------------- 1 | LIBFDT_1.2 { 2 | global: 3 | fdt_next_node; 4 | fdt_check_header; 5 | fdt_move; 6 | fdt_string; 7 | fdt_num_mem_rsv; 8 | fdt_get_mem_rsv; 9 | fdt_subnode_offset_namelen; 10 | fdt_subnode_offset; 11 | fdt_path_offset; 12 | fdt_get_name; 13 | fdt_get_property_namelen; 14 | fdt_get_property; 15 | fdt_getprop_namelen; 16 | fdt_getprop; 17 | fdt_get_phandle; 18 | fdt_get_alias_namelen; 19 | fdt_get_alias; 20 | fdt_get_path; 21 | fdt_supernode_atdepth_offset; 22 | fdt_node_depth; 23 | fdt_parent_offset; 24 | fdt_node_offset_by_prop_value; 25 | fdt_node_offset_by_phandle; 26 | fdt_node_check_compatible; 27 | fdt_node_offset_by_compatible; 28 | fdt_setprop_inplace; 29 | fdt_nop_property; 30 | fdt_nop_node; 31 | fdt_create; 32 | fdt_add_reservemap_entry; 33 | fdt_finish_reservemap; 34 | fdt_begin_node; 35 | fdt_property; 36 | fdt_end_node; 37 | fdt_finish; 38 | fdt_open_into; 39 | fdt_pack; 40 | fdt_add_mem_rsv; 41 | fdt_del_mem_rsv; 42 | fdt_set_name; 43 | fdt_setprop; 44 | fdt_delprop; 45 | fdt_add_subnode_namelen; 46 | fdt_add_subnode; 47 | fdt_del_node; 48 | fdt_strerror; 49 | fdt_offset_ptr; 50 | fdt_next_tag; 51 | fdt_appendprop; 52 | fdt_create_empty_tree; 53 | fdt_first_property_offset; 54 | fdt_get_property_by_offset; 55 | fdt_getprop_by_offset; 56 | fdt_next_property_offset; 57 | 58 | local: 59 | *; 60 | }; 61 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/acpi.c: -------------------------------------------------------------------------------- 1 | #include "libcflat.h" 2 | #include "acpi.h" 3 | 4 | void* find_acpi_table_addr(u32 sig) 5 | { 6 | unsigned long addr; 7 | struct rsdp_descriptor *rsdp; 8 | struct rsdt_descriptor_rev1 *rsdt; 9 | void *end; 10 | int i; 11 | 12 | /* FACS is special... */ 13 | if (sig == FACS_SIGNATURE) { 14 | struct fadt_descriptor_rev1 *fadt; 15 | fadt = find_acpi_table_addr(FACP_SIGNATURE); 16 | if (!fadt) { 17 | return NULL; 18 | } 19 | return (void*)(ulong)fadt->firmware_ctrl; 20 | } 21 | 22 | for(addr = 0xf0000; addr < 0x100000; addr += 16) { 23 | rsdp = (void*)addr; 24 | if (rsdp->signature == 0x2052545020445352LL) 25 | break; 26 | } 27 | if (addr == 0x100000) { 28 | printf("Can't find RSDP\n"); 29 | return 0; 30 | } 31 | 32 | if (sig == RSDP_SIGNATURE) { 33 | return rsdp; 34 | } 35 | 36 | rsdt = (void*)(ulong)rsdp->rsdt_physical_address; 37 | if (!rsdt || rsdt->signature != RSDT_SIGNATURE) 38 | return 0; 39 | 40 | if (sig == RSDT_SIGNATURE) { 41 | return rsdt; 42 | } 43 | 44 | end = (void*)rsdt + rsdt->length; 45 | for (i=0; (void*)&rsdt->table_offset_entry[i] < end; i++) { 46 | struct acpi_table *t = (void*)(ulong)rsdt->table_offset_entry[i]; 47 | if (t && t->signature == sig) { 48 | return t; 49 | } 50 | } 51 | return NULL; 52 | } 53 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/fwcfg.h: -------------------------------------------------------------------------------- 1 | #ifndef FWCFG_H 2 | #define FWCFG_H 3 | 4 | #include 5 | 6 | #define FW_CFG_SIGNATURE 0x00 7 | #define FW_CFG_ID 0x01 8 | #define FW_CFG_UUID 0x02 9 | #define FW_CFG_RAM_SIZE 0x03 10 | #define FW_CFG_NOGRAPHIC 0x04 11 | #define FW_CFG_NB_CPUS 0x05 12 | #define FW_CFG_MACHINE_ID 0x06 13 | #define FW_CFG_KERNEL_ADDR 0x07 14 | #define FW_CFG_KERNEL_SIZE 0x08 15 | #define FW_CFG_KERNEL_CMDLINE 0x09 16 | #define FW_CFG_INITRD_ADDR 0x0a 17 | #define FW_CFG_INITRD_SIZE 0x0b 18 | #define FW_CFG_BOOT_DEVICE 0x0c 19 | #define FW_CFG_NUMA 0x0d 20 | #define FW_CFG_BOOT_MENU 0x0e 21 | #define FW_CFG_MAX_CPUS 0x0f 22 | #define FW_CFG_MAX_ENTRY 0x10 23 | 24 | #define FW_CFG_WRITE_CHANNEL 0x4000 25 | #define FW_CFG_ARCH_LOCAL 0x8000 26 | #define FW_CFG_ENTRY_MASK ~(FW_CFG_WRITE_CHANNEL | FW_CFG_ARCH_LOCAL) 27 | 28 | #define FW_CFG_INVALID 0xffff 29 | 30 | #define BIOS_CFG_IOPORT 0x510 31 | 32 | #define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0) 33 | #define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1) 34 | #define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2) 35 | 36 | uint8_t fwcfg_get_u8(unsigned index); 37 | uint16_t fwcfg_get_u16(unsigned index); 38 | uint32_t fwcfg_get_u32(unsigned index); 39 | uint64_t fwcfg_get_u64(unsigned index); 40 | 41 | unsigned fwcfg_get_nb_cpus(void); 42 | 43 | #endif 44 | 45 | -------------------------------------------------------------------------------- /tests/api/reset.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | // This test checks that reset works 5 | 6 | const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD; 7 | 8 | const fs = require("fs"); 9 | var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86; 10 | 11 | process.on("unhandledRejection", exn => { throw exn; }); 12 | 13 | const config = { 14 | bios: { url: __dirname + "/../../bios/seabios.bin" }, 15 | vga_bios: { url: __dirname + "/../../bios/vgabios.bin" }, 16 | cdrom: { url: __dirname + "/../../images/linux4.iso", async: true }, 17 | network_relay_url: "", 18 | autostart: true, 19 | memory_size: 32 * 1024 * 1024, 20 | filesystem: {}, 21 | log_level: 0, 22 | disable_jit: +process.env.DISABLE_JIT, 23 | screen_dummy: true, 24 | }; 25 | 26 | const emulator = new V86(config); 27 | 28 | let did_restart = false; 29 | let serial_text = ""; 30 | 31 | emulator.add_listener("serial0-output-byte", function(byte) 32 | { 33 | var chr = String.fromCharCode(byte); 34 | serial_text += chr; 35 | 36 | if(serial_text.includes("Files send via emulator appear in /mnt/")) { 37 | serial_text = ""; 38 | if(did_restart) { 39 | console.log("Ok"); 40 | emulator.stop(); 41 | } 42 | else { 43 | console.log("Calling restart()"); 44 | emulator.restart(); 45 | did_restart = true; 46 | } 47 | } 48 | }); 49 | -------------------------------------------------------------------------------- /src/browser/worker_bus.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var WorkerBus = {}; 4 | 5 | /** @constructor */ 6 | WorkerBus.Connector = function(pair) 7 | { 8 | this.listeners = {}; 9 | this.pair = pair; 10 | 11 | pair.addEventListener("message", function(e) 12 | { 13 | var data = e.data; 14 | var listeners = this.listeners[data[0]]; 15 | 16 | for(var i = 0; i < listeners.length; i++) 17 | { 18 | var listener = listeners[i]; 19 | listener.fn.call(listener.this_value, data[1]); 20 | } 21 | }.bind(this), false); 22 | 23 | }; 24 | 25 | WorkerBus.Connector.prototype.register = function(name, fn, this_value) 26 | { 27 | var listeners = this.listeners[name]; 28 | 29 | if(listeners === undefined) 30 | { 31 | listeners = this.listeners[name] = []; 32 | } 33 | 34 | listeners.push({ 35 | fn: fn, 36 | this_value: this_value, 37 | }); 38 | }; 39 | 40 | /** 41 | * Send ("emit") a message 42 | * 43 | * @param {string} name 44 | * @param {*=} value 45 | * @param {*=} transfer_list 46 | */ 47 | WorkerBus.Connector.prototype.send = function(name, value, transfer_list) 48 | { 49 | dbg_assert(arguments.length >= 1); 50 | 51 | if(!this.pair) 52 | { 53 | return; 54 | } 55 | 56 | this.pair.postMessage([name, value], transfer_list); 57 | }; 58 | 59 | 60 | WorkerBus.init = function(worker) 61 | { 62 | return new WorkerBus.Connector(worker); 63 | }; 64 | 65 | -------------------------------------------------------------------------------- /docs/linux-9p-image.md: -------------------------------------------------------------------------------- 1 | In order to create a Linux image that can mount the 9p file system, add the following lines to the kernel configuration: 2 | 3 | ``` 4 | CONFIG_NET_9P=y 5 | CONFIG_NET_9P_VIRTIO=y 6 | CONFIG_NET_9P_DEBUG=y 7 | CONFIG_VIRTIO=y 8 | CONFIG_VIRTIO_PCI=y 9 | CONFIG_9P_FS=y 10 | CONFIG_9P_FSCACHE=y 11 | CONFIG_9P_FS_POSIX_ACL=y 12 | ``` 13 | 14 | A Dockerfile for this build is here: https://github.com/ysangkok/build-v86-9p-linux 15 | 16 | Using initcpio 17 | -------------- 18 | 19 | This allows you to remount the root file system using 9p. No changes are necessary if you only want to mount a 9p filesystem after booting. 20 | 21 | Add the following files: 22 | 23 | `/etc/initcpio/hooks/9p_root` 24 | 25 | ```bash 26 | #!/usr/bin/bash 27 | 28 | run_hook() { 29 | mount_handler="mount_9p_root" 30 | } 31 | 32 | mount_9p_root() { 33 | msg ":: mounting '$root' on real root (9p)" 34 | if ! mount -t 9p host9p "$1"; then 35 | echo "You are now being dropped into an emergency shell." 36 | launch_interactive_shell 37 | msg "Trying to continue (this will most likely fail) ..." 38 | fi 39 | } 40 | ``` 41 | 42 |
43 | 44 | `/etc/initcpio/install/9p_root` 45 | 46 | ```bash 47 | #!/bin/bash 48 | build() { 49 | add_runscript 50 | } 51 | ``` 52 | 53 | Change the following options in `/etc/mkinitcpio.conf`: 54 | 55 | ```bash 56 | MODULES="virtio_pci 9p 9pnet 9pnet_virtio" 57 | HOOKS="base udev autodetect modconf block filesystems keyboard fsck 9p_root" # appended 9p_root 58 | ``` 59 | -------------------------------------------------------------------------------- /docs/cpu-idling.md: -------------------------------------------------------------------------------- 1 | Some operating systems don't support `hlt` instruction, because of this, the CPU spin loops instead of idling. 2 | Here are some solutions for different OSes: 3 | 4 | ## MS-DOS (using DOSIdle) 5 | 1. Download `DOSID251.zip` from https://www.vogons.org/viewtopic.php?p=438763#p438763 6 | 2. Unzip DOSIDLE.EXE from archive in any location (recommended to root of C:). 7 | 3. Run `edit C:\autoexec.bat` 8 | 4. Add to file: `C:\path\to\dosidle.exe` 9 | 5. Save changes (*press Alt + F and x*) and restart the VM. 10 | 11 | **Note:** To hide output when starting DOSIdle, change `C:\path\to\dosidle.exe` to `C:\path\to\dosidle.exe > nul` on step №4. 12 | 13 | ## FreeDOS ([source](https://narkive.com/UGrcO8wU.2)) 14 | 1. Run `edit C:\fdconfig.sys` (or `edit C:\config.sys`) 15 | 2. Add to file: `IDLEHALT=1` 16 | 3. Save changes (*press Alt + F and x*) and restart FreeDOS. 17 | 18 | ## Windows 9x (using AmnHLT) 19 | 1. Download `amnhltm.zip` from http://toogam.com/software/archive/drivers/cpu/cpuidle/amnhltm.zip ([mirror](https://web.archive.org/web/20060212132151/http://www.user.cityline.ru/~maxamn/amnhltm.zip)) 20 | 2. Unzip the archive in any location. 21 | 3. **Note**: If you have installed VBE9x, restart Windows, press F8 on boot, select *Command prompt only*, run `cd C:\path\to\amnhlt\`, and follow to the next step. 22 | 4. Run `AMNHLT.BAT` 23 | 5. Restart Windows, and AmnHLT will start automatically on next boot (you can safely delete archive and unpacked folder). 24 | 25 | ## Windows 98+ and Unix-like 26 | These systems are already supports `hlt`, no further action is required. 27 | -------------------------------------------------------------------------------- /src/rust/leb.rs: -------------------------------------------------------------------------------- 1 | pub fn write_leb_i32(buf: &mut Vec, v: i32) { write_leb_i64(buf, v as i64); } 2 | 3 | pub fn write_leb_i64(buf: &mut Vec, mut v: i64) { 4 | // https://en.wikipedia.org/wiki/LEB128#Encode_signed_integer 5 | loop { 6 | let mut byte = v as u8 & 0b0111_1111; 7 | v >>= 7; 8 | let sign = byte & (1 << 6); 9 | let done = v == 0 && sign == 0 || v == -1 && sign != 0; 10 | if !done { 11 | byte |= 0b1000_0000; 12 | } 13 | buf.push(byte); 14 | if done { 15 | break; 16 | } 17 | } 18 | } 19 | 20 | pub fn write_leb_u32(buf: &mut Vec, mut v: u32) { 21 | loop { 22 | let mut byte = v as u8 & 0b0111_1111; 23 | v >>= 7; 24 | if v != 0 { 25 | byte |= 0b1000_0000; 26 | } 27 | buf.push(byte); 28 | if v == 0 { 29 | break; 30 | } 31 | } 32 | } 33 | 34 | pub fn write_fixed_leb16_at_idx(vec: &mut Vec, idx: usize, x: u16) { 35 | dbg_assert!(x < (1 << 14)); // we have 14 bits of available space in 2 bytes for leb 36 | vec[idx] = ((x & 0b1111111) | 0b10000000) as u8; 37 | vec[idx + 1] = (x >> 7) as u8; 38 | } 39 | 40 | pub fn write_fixed_leb32_at_idx(vec: &mut Vec, idx: usize, x: u32) { 41 | dbg_assert!(x < (1 << 28)); // we have 28 bits of available space in 4 bytes for leb 42 | vec[idx] = (x & 0b1111111) as u8 | 0b10000000; 43 | vec[idx + 1] = (x >> 7 & 0b1111111) as u8 | 0b10000000; 44 | vec[idx + 2] = (x >> 14 & 0b1111111) as u8 | 0b10000000; 45 | vec[idx + 3] = (x >> 21 & 0b1111111) as u8; 46 | } 47 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/chr-testdev.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014, Red Hat Inc, Andrew Jones 3 | * 4 | * This work is licensed under the terms of the GNU LGPL, version 2. 5 | */ 6 | #include "libcflat.h" 7 | #include "virtio.h" 8 | #include "asm/spinlock.h" 9 | 10 | #define TESTDEV_NAME "chr-testdev" 11 | 12 | static struct virtio_device *vcon; 13 | static struct virtqueue *in_vq, *out_vq; 14 | static struct spinlock lock; 15 | 16 | static void __testdev_send(char *buf, unsigned int len) 17 | { 18 | int ret; 19 | 20 | ret = virtqueue_add_outbuf(out_vq, buf, len); 21 | virtqueue_kick(out_vq); 22 | 23 | if (ret < 0) 24 | return; 25 | 26 | while (!virtqueue_get_buf(out_vq, &len)) 27 | ; 28 | } 29 | 30 | void chr_testdev_exit(int code) 31 | { 32 | unsigned int len; 33 | char buf[8]; 34 | 35 | snprintf(buf, sizeof(buf), "%dq", code); 36 | len = strlen(buf); 37 | 38 | spin_lock(&lock); 39 | 40 | if (!vcon) 41 | goto out; 42 | 43 | __testdev_send(buf, len); 44 | 45 | out: 46 | spin_unlock(&lock); 47 | } 48 | 49 | void chr_testdev_init(void) 50 | { 51 | const char *io_names[] = { "input", "output" }; 52 | struct virtqueue *vqs[2]; 53 | int ret; 54 | 55 | vcon = virtio_bind(VIRTIO_ID_CONSOLE); 56 | if (vcon == NULL) { 57 | printf("%s: %s: can't find a virtio-console\n", 58 | __func__, TESTDEV_NAME); 59 | return; 60 | } 61 | 62 | ret = vcon->config->find_vqs(vcon, 2, vqs, NULL, io_names); 63 | if (ret < 0) { 64 | printf("%s: %s: can't init virtqueues\n", 65 | __func__, TESTDEV_NAME); 66 | vcon = NULL; 67 | return; 68 | } 69 | 70 | in_vq = vqs[0]; 71 | out_vq = vqs[1]; 72 | } 73 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/run.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | process.on("unhandledRejection", exn => { throw exn; }); 5 | 6 | const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD; 7 | 8 | var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86; 9 | var fs = require("fs"); 10 | 11 | function readfile(path) 12 | { 13 | return new Uint8Array(fs.readFileSync(path)).buffer; 14 | } 15 | 16 | function Loader(path) 17 | { 18 | this.buffer = readfile(path); 19 | this.byteLength = this.buffer.byteLength; 20 | } 21 | 22 | Loader.prototype.load = function() 23 | { 24 | this.onload && this.onload({}); 25 | }; 26 | 27 | var bios = readfile(__dirname + "/../../bios/seabios.bin"); 28 | var vga_bios = readfile(__dirname + "/../../bios/vgabios.bin"); 29 | 30 | var emulator = new V86({ 31 | bios: { buffer: bios }, 32 | vga_bios: { buffer: vga_bios }, 33 | multiboot: new Loader(process.argv[2]), 34 | autostart: true, 35 | memory_size: 64 * 1024 * 1024, 36 | disable_jit: +process.env.DISABLE_JIT, 37 | log_level: 0, 38 | }); 39 | 40 | emulator.bus.register("emulator-started", function() 41 | { 42 | emulator.v86.cpu.io.register_write_consecutive(0xF4, {}, 43 | function(value) 44 | { 45 | console.log("Test exited with code " + value); 46 | process.exit(value); 47 | }, 48 | function() {}, 49 | function() {}, 50 | function() {}); 51 | }); 52 | 53 | emulator.add_listener("serial0-output-byte", function(byte) 54 | { 55 | var chr = String.fromCharCode(byte); 56 | process.stdout.write(chr); 57 | }); 58 | 59 | -------------------------------------------------------------------------------- /examples/nodejs_state.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | var fs = require("fs"); 5 | var V86 = require("../build/libv86.js").V86; 6 | 7 | function readfile(path) 8 | { 9 | return new Uint8Array(fs.readFileSync(path)).buffer; 10 | } 11 | 12 | console.log("Use F2 to save the state and F3 to restore."); 13 | 14 | var bios = readfile(__dirname + "/../bios/seabios.bin"); 15 | var linux = readfile(__dirname + "/../images/linux4.iso"); 16 | 17 | process.stdin.setRawMode(true); 18 | process.stdin.resume(); 19 | process.stdin.setEncoding("utf8"); 20 | 21 | console.log("Now booting, please stand by ..."); 22 | 23 | var emulator = new V86({ 24 | bios: { buffer: bios }, 25 | cdrom: { buffer: linux }, 26 | autostart: true, 27 | }); 28 | 29 | emulator.add_listener("serial0-output-byte", function(byte) 30 | { 31 | var chr = String.fromCharCode(byte); 32 | if(chr <= "~") 33 | { 34 | process.stdout.write(chr); 35 | } 36 | }); 37 | 38 | var state; 39 | 40 | process.stdin.on("data", async function(c) 41 | { 42 | if(c === "\u0003") 43 | { 44 | // ctrl c 45 | emulator.stop(); 46 | process.stdin.pause(); 47 | } 48 | else if(c === "\x1b\x4f\x51") 49 | { 50 | // f2 51 | state = await emulator.save_state(); 52 | console.log("--- Saved ---"); 53 | } 54 | else if(c === "\x1b\x4f\x52") 55 | { 56 | // f3 57 | if(state) 58 | { 59 | console.log("--- Restored ---"); 60 | await emulator.restore_state(state); 61 | } 62 | } 63 | else 64 | { 65 | emulator.serial0_send(c); 66 | } 67 | }); 68 | -------------------------------------------------------------------------------- /tests/qemu/test-i386-code16.S: -------------------------------------------------------------------------------- 1 | .code16 2 | .globl code16_start 3 | .globl code16_end 4 | 5 | CS_SEG = 0xf 6 | 7 | code16_start: 8 | 9 | .globl code16_func1 10 | 11 | /* basic test */ 12 | code16_func1 = . - code16_start 13 | mov $1, %eax 14 | data32 lret 15 | 16 | /* test push/pop in 16 bit mode */ 17 | .globl code16_func2 18 | code16_func2 = . - code16_start 19 | xor %eax, %eax 20 | mov $0x12345678, %ebx 21 | movl %esp, %ecx 22 | push %bx 23 | subl %esp, %ecx 24 | pop %ax 25 | data32 lret 26 | 27 | /* test various jmp opcodes */ 28 | .globl code16_func3 29 | code16_func3 = . - code16_start 30 | jmp 1f 31 | nop 32 | 1: 33 | mov $4, %eax 34 | mov $0x12345678, %ebx 35 | xor %bx, %bx 36 | jz 2f 37 | add $2, %ax 38 | 2: 39 | 40 | call myfunc 41 | 42 | lcall $CS_SEG, $(myfunc2 - code16_start) 43 | 44 | ljmp $CS_SEG, $(myjmp1 - code16_start) 45 | myjmp1_next: 46 | 47 | cs lcall *myfunc2_addr - code16_start 48 | 49 | cs ljmp *myjmp2_addr - code16_start 50 | myjmp2_next: 51 | 52 | data32 lret 53 | 54 | myfunc2_addr: 55 | .short myfunc2 - code16_start 56 | .short CS_SEG 57 | 58 | myjmp2_addr: 59 | .short myjmp2 - code16_start 60 | .short CS_SEG 61 | 62 | myjmp1: 63 | add $8, %ax 64 | jmp myjmp1_next 65 | 66 | myjmp2: 67 | add $16, %ax 68 | jmp myjmp2_next 69 | 70 | myfunc: 71 | add $1, %ax 72 | ret 73 | 74 | myfunc2: 75 | add $4, %ax 76 | lret 77 | 78 | 79 | code16_end: 80 | -------------------------------------------------------------------------------- /lib/utf8.js: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------- 2 | // ------------------ UTF8 Helpers ----------------- 3 | // ------------------------------------------------- 4 | 5 | "use strict"; 6 | 7 | var UTF8 = {}; 8 | 9 | /** @constructor */ 10 | function UTF8StreamToUnicode() { 11 | 12 | this.stream = new Uint8Array(5); 13 | this.ofs = 0; 14 | 15 | this.Put = function(key) { 16 | this.stream[this.ofs] = key; 17 | this.ofs++; 18 | switch(this.ofs) { 19 | case 1: 20 | if (this.stream[0] < 128) { 21 | this.ofs = 0; 22 | return this.stream[0]; 23 | } 24 | break; 25 | 26 | case 2: 27 | if ((this.stream[0]&0xE0) == 0xC0) 28 | if ((this.stream[1]&0xC0) == 0x80) { 29 | this.ofs = 0; 30 | return ((this.stream[0]&0x1F)<<6) | (this.stream[1]&0x3F); 31 | } 32 | break; 33 | 34 | case 3: 35 | break; 36 | 37 | case 4: 38 | break; 39 | 40 | default: 41 | return -1; 42 | //this.ofs = 0; 43 | //break; 44 | } 45 | return -1; 46 | }; 47 | } 48 | 49 | function UnicodeToUTF8Stream(key) 50 | { 51 | if (key < 0x80) return [key]; 52 | if (key < 0x800) return [0xC0|((key>>6)&0x1F), 0x80|(key&0x3F)]; 53 | } 54 | 55 | UTF8.UTF8Length = function(s) 56 | { 57 | var length = 0; 58 | for(var i=0; i 5 | * 6 | * This work is licensed under the terms of the GNU LGPL, version 2. 7 | */ 8 | #include "libcflat.h" 9 | #include "pci.h" 10 | #include "x86/asm/io.h" 11 | 12 | #define PCI_CONF1_ADDRESS(dev, reg) ((0x1 << 31) | (dev << 8) | reg) 13 | 14 | static inline uint8_t pci_config_readb(pcidevaddr_t dev, uint8_t reg) 15 | { 16 | outl(PCI_CONF1_ADDRESS(dev, reg), 0xCF8); 17 | return inb(0xCFC); 18 | } 19 | 20 | static inline uint16_t pci_config_readw(pcidevaddr_t dev, uint8_t reg) 21 | { 22 | outl(PCI_CONF1_ADDRESS(dev, reg), 0xCF8); 23 | return inw(0xCFC); 24 | } 25 | 26 | static inline uint32_t pci_config_readl(pcidevaddr_t dev, uint8_t reg) 27 | { 28 | outl(PCI_CONF1_ADDRESS(dev, reg), 0xCF8); 29 | return inl(0xCFC); 30 | } 31 | 32 | static inline void pci_config_writeb(pcidevaddr_t dev, uint8_t reg, 33 | uint8_t val) 34 | { 35 | outl(PCI_CONF1_ADDRESS(dev, reg), 0xCF8); 36 | outb(val, 0xCFC); 37 | } 38 | 39 | static inline void pci_config_writew(pcidevaddr_t dev, uint8_t reg, 40 | uint16_t val) 41 | { 42 | outl(PCI_CONF1_ADDRESS(dev, reg), 0xCF8); 43 | outw(val, 0xCFC); 44 | } 45 | 46 | static inline void pci_config_writel(pcidevaddr_t dev, uint8_t reg, 47 | uint32_t val) 48 | { 49 | outl(PCI_CONF1_ADDRESS(dev, reg), 0xCF8); 50 | outl(val, 0xCFC); 51 | } 52 | 53 | static inline 54 | phys_addr_t pci_translate_addr(pcidevaddr_t dev __unused, uint64_t addr) 55 | { 56 | return addr; 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /tests/api/serial.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD; 5 | 6 | const assert = require("assert").strict; 7 | const fs = require("fs"); 8 | const crypto = require("crypto"); 9 | var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86; 10 | 11 | process.on("unhandledRejection", exn => { throw exn; }); 12 | 13 | const config = { 14 | bios: { url: __dirname + "/../../bios/seabios.bin" }, 15 | vga_bios: { url: __dirname + "/../../bios/vgabios.bin" }, 16 | cdrom: { url: __dirname + "/../../images/linux.iso" }, 17 | network_relay_url: "", 18 | autostart: true, 19 | memory_size: 32 * 1024 * 1024, 20 | filesystem: {}, 21 | log_level: 0, 22 | disable_jit: +process.env.DISABLE_JIT, 23 | screen_dummy: true, 24 | }; 25 | 26 | const emulator = new V86(config); 27 | 28 | let serial_data = []; 29 | 30 | emulator.automatically([ 31 | { sleep: 1 }, 32 | { vga_text: "/root% " }, 33 | { call: () => { console.log("Booted, sending file to ttyS0"); } }, 34 | { keyboard_send: "cat /bin/busybox > /dev/ttyS0\n" }, 35 | ]); 36 | 37 | const timeout = setTimeout(() => { 38 | throw new Error("Timeout"); 39 | }, 60 * 1000); 40 | 41 | emulator.add_listener("serial0-output-byte", function(byte) 42 | { 43 | serial_data.push(byte); 44 | 45 | if(serial_data.length === 510277) 46 | { 47 | const hash = crypto.createHash("sha256"); 48 | hash.update(new Uint8Array(serial_data)); 49 | assert("da1fb5b421123c58080a59832675632505b8c139a8d7ecd1c31591ca5c65cea6" === hash.digest("hex")); 50 | console.log("ok"); 51 | clearTimeout(timeout); 52 | emulator.stop(); 53 | } 54 | }); 55 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/asm/io.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASM_X86_IO_H_ 2 | #define _ASM_X86_IO_H_ 3 | 4 | #define __iomem 5 | 6 | #define inb inb 7 | static inline uint8_t inb(unsigned long port) 8 | { 9 | unsigned char value; 10 | asm volatile("inb %w1, %0" : "=a" (value) : "Nd" ((unsigned short)port)); 11 | return value; 12 | } 13 | 14 | #define inw inw 15 | static inline uint16_t inw(unsigned long port) 16 | { 17 | unsigned short value; 18 | asm volatile("inw %w1, %0" : "=a" (value) : "Nd" ((unsigned short)port)); 19 | return value; 20 | } 21 | 22 | #define inl inl 23 | static inline uint32_t inl(unsigned long port) 24 | { 25 | unsigned int value; 26 | asm volatile("inl %w1, %0" : "=a" (value) : "Nd" ((unsigned short)port)); 27 | return value; 28 | } 29 | 30 | #define outb outb 31 | static inline void outb(uint8_t value, unsigned long port) 32 | { 33 | asm volatile("outb %b0, %w1" : : "a"(value), "Nd"((unsigned short)port)); 34 | } 35 | 36 | #define outw outw 37 | static inline void outw(uint16_t value, unsigned long port) 38 | { 39 | asm volatile("outw %w0, %w1" : : "a"(value), "Nd"((unsigned short)port)); 40 | } 41 | 42 | #define outl outl 43 | static inline void outl(uint32_t value, unsigned long port) 44 | { 45 | asm volatile("outl %0, %w1" : : "a"(value), "Nd"((unsigned short)port)); 46 | } 47 | 48 | #define virt_to_phys virt_to_phys 49 | static inline unsigned long virt_to_phys(const void *virt) 50 | { 51 | return (unsigned long)virt; 52 | } 53 | 54 | #define phys_to_virt phys_to_virt 55 | static inline void *phys_to_virt(unsigned long phys) 56 | { 57 | return (void *)phys; 58 | } 59 | 60 | #define ioremap ioremap 61 | void __iomem *ioremap(phys_addr_t phys_addr, size_t size); 62 | 63 | #include 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /tools/docker/debian/xorg.conf: -------------------------------------------------------------------------------- 1 | Section "ServerLayout" 2 | Identifier "X.org Configured" 3 | Screen 0 "Screen0" 0 0 4 | InputDevice "Mouse0" "CorePointer" 5 | InputDevice "Keyboard0" "CoreKeyboard" 6 | EndSection 7 | 8 | Section "Files" 9 | ModulePath "/usr/lib/xorg/modules" 10 | FontPath "/usr/share/fonts/misc/" 11 | FontPath "/usr/share/fonts/TTF/" 12 | #FontPath "/usr/share/fonts/OTF/" 13 | #FontPath "/usr/share/fonts/Type1/" 14 | FontPath "/usr/share/fonts/100dpi/" 15 | FontPath "/usr/share/fonts/75dpi/" 16 | EndSection 17 | 18 | Section "Module" 19 | Load "glx" 20 | EndSection 21 | 22 | Section "InputDevice" 23 | Identifier "Keyboard0" 24 | Driver "kbd" 25 | EndSection 26 | 27 | Section "InputDevice" 28 | Identifier "Mouse0" 29 | Driver "mouse" 30 | Option "Protocol" "auto" 31 | Option "Device" "/dev/input/mice" 32 | Option "ZAxisMapping" "4 5 6 7" 33 | EndSection 34 | 35 | Section "Monitor" 36 | Identifier "Monitor0" 37 | VendorName "Monitor Vendor" 38 | ModelName "Monitor Model" 39 | EndSection 40 | 41 | Section "Device" 42 | ### Available Driver options are:- 43 | ### Values: : integer, : float, : "True"/"False", 44 | ### : "String", : " Hz/kHz/MHz", 45 | ### : "%" 46 | ### [arg]: arg optional 47 | #Option "ShadowFB" # [] 48 | #Option "Rotate" # 49 | #Option "fbdev" # 50 | #Option "debug" # [] 51 | Identifier "Card0" 52 | Driver "fbdev" 53 | #BusID "PCI:0:2:0" 54 | Driver "vesa" 55 | EndSection 56 | 57 | Section "Screen" 58 | Identifier "Screen0" 59 | Device "Card0" 60 | Monitor "Monitor0" 61 | SubSection "Display" 62 | #Viewport 0 0 63 | Depth 24 64 | Modes "1280x1024" 65 | EndSubSection 66 | EndSection 67 | 68 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/vm.h: -------------------------------------------------------------------------------- 1 | #ifndef VM_H 2 | #define VM_H 3 | 4 | #include "processor.h" 5 | #include "asm/page.h" 6 | #include "asm/io.h" 7 | 8 | void setup_vm(); 9 | 10 | void *vmalloc(unsigned long size); 11 | void vfree(void *mem); 12 | void *vmap(unsigned long long phys, unsigned long size); 13 | void *alloc_vpage(void); 14 | void *alloc_vpages(ulong nr); 15 | uint64_t virt_to_phys_cr3(void *mem); 16 | 17 | struct pte_search { 18 | int level; 19 | unsigned long *pte; 20 | }; 21 | 22 | static inline bool found_huge_pte(struct pte_search search) 23 | { 24 | return (search.level == 2 || search.level == 3) && 25 | (*search.pte & PT_PRESENT_MASK) && 26 | (*search.pte & PT_PAGE_SIZE_MASK); 27 | } 28 | 29 | static inline bool found_leaf_pte(struct pte_search search) 30 | { 31 | return search.level == 1 || found_huge_pte(search); 32 | } 33 | 34 | struct pte_search find_pte_level(unsigned long *cr3, void *virt, 35 | int lowest_level); 36 | unsigned long *get_pte(unsigned long *cr3, void *virt); 37 | unsigned long *get_pte_level(unsigned long *cr3, void *virt, int pte_level); 38 | unsigned long *install_pte(unsigned long *cr3, 39 | int pte_level, 40 | void *virt, 41 | unsigned long pte, 42 | unsigned long *pt_page); 43 | 44 | void *alloc_page(); 45 | void *alloc_pages(unsigned long order); 46 | void free_page(void *page); 47 | 48 | unsigned long *install_large_page(unsigned long *cr3,unsigned long phys, 49 | void *virt); 50 | unsigned long *install_page(unsigned long *cr3, unsigned long phys, void *virt); 51 | void install_pages(unsigned long *cr3, unsigned long phys, unsigned long len, 52 | void *virt); 53 | bool any_present_pages(unsigned long *cr3, void *virt, unsigned long len); 54 | 55 | static inline void *current_page_table(void) 56 | { 57 | return phys_to_virt(read_cr3()); 58 | } 59 | #endif 60 | -------------------------------------------------------------------------------- /tools/rust-lld-wrapper: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # A wrapper for rust-lld that removes certain arguments inserted by rustc that 4 | # we'd like to override 5 | 6 | import sys 7 | import subprocess 8 | import re 9 | from os import path 10 | 11 | def main(): 12 | args = sys.argv[1:] 13 | 14 | strip_debug = "--v86-strip-debug" in args 15 | 16 | # filter out args inserted by rustc 17 | TO_REMOVE = { 18 | "--export-table", 19 | "--stack-first", 20 | "--strip-debug", 21 | "--v86-strip-debug", 22 | } 23 | args = list(filter(lambda arg: arg not in TO_REMOVE, args)) 24 | 25 | if strip_debug: 26 | args += ["--strip-debug"] 27 | 28 | lld = find_rust_lld() 29 | 30 | result = subprocess.run([lld] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 31 | 32 | print(result.stderr, file=sys.stderr) 33 | print(result.stdout) 34 | 35 | result.check_returncode() 36 | 37 | def find_host_triplet(): 38 | rustc = subprocess.run(["rustc", "--version", "--verbose"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 39 | rustc.check_returncode() 40 | 41 | rustc_details = rustc.stdout.decode("utf8") 42 | host = re.search(r"host: (.*)", rustc_details) 43 | if host is None: 44 | raise ValueError("unexpected rustc output") 45 | return host.group(1) 46 | 47 | def find_rust_lld(): 48 | try: 49 | which = subprocess.run(["rustup", "which", "rustc"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 50 | except FileNotFoundError: 51 | return "lld" 52 | which.check_returncode() 53 | 54 | rustc_path = which.stdout.decode("utf8").strip() 55 | assert path.basename(rustc_path) == "rustc" 56 | 57 | bin_path = path.dirname(rustc_path) 58 | triplet = find_host_triplet() 59 | 60 | rust_lld_path = path.join(bin_path, "../lib/rustlib", triplet, "bin/rust-lld") 61 | assert path.isfile(rust_lld_path) 62 | 63 | return rust_lld_path 64 | 65 | main() 66 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/hyperv.c: -------------------------------------------------------------------------------- 1 | #include "hyperv.h" 2 | #include "asm/io.h" 3 | #include "smp.h" 4 | 5 | enum { 6 | HV_TEST_DEV_SINT_ROUTE_CREATE = 1, 7 | HV_TEST_DEV_SINT_ROUTE_DESTROY, 8 | HV_TEST_DEV_SINT_ROUTE_SET_SINT, 9 | HV_TEST_DEV_MSG_CONN_CREATE, 10 | HV_TEST_DEV_MSG_CONN_DESTROY, 11 | HV_TEST_DEV_EVT_CONN_CREATE, 12 | HV_TEST_DEV_EVT_CONN_DESTROY, 13 | }; 14 | 15 | static void synic_ctl(u32 ctl, u32 vcpu_id, u32 sint, u32 conn_id) 16 | { 17 | outl((conn_id << 24) | (ctl << 16) | (vcpu_id << 8) | sint, 0x3000); 18 | } 19 | 20 | static void sint_enable(u8 sint, u8 vec, bool auto_eoi) 21 | { 22 | wrmsr(HV_X64_MSR_SINT0 + sint, 23 | (u64)vec | (auto_eoi ? HV_SYNIC_SINT_AUTO_EOI : 0)); 24 | } 25 | 26 | static void sint_disable(u8 sint) 27 | { 28 | wrmsr(HV_X64_MSR_SINT0 + sint, 0xff | HV_SYNIC_SINT_MASKED); 29 | } 30 | 31 | void synic_sint_create(u8 sint, u8 vec, bool auto_eoi) 32 | { 33 | synic_ctl(HV_TEST_DEV_SINT_ROUTE_CREATE, smp_id(), sint, 0); 34 | sint_enable(sint, vec, auto_eoi); 35 | } 36 | 37 | void synic_sint_set(u8 vcpu, u8 sint) 38 | { 39 | synic_ctl(HV_TEST_DEV_SINT_ROUTE_SET_SINT, vcpu, sint, 0); 40 | } 41 | 42 | void synic_sint_destroy(u8 sint) 43 | { 44 | sint_disable(sint); 45 | synic_ctl(HV_TEST_DEV_SINT_ROUTE_DESTROY, smp_id(), sint, 0); 46 | } 47 | 48 | void msg_conn_create(u8 sint, u8 vec, u8 conn_id) 49 | { 50 | synic_ctl(HV_TEST_DEV_MSG_CONN_CREATE, smp_id(), sint, conn_id); 51 | sint_enable(sint, vec, true); 52 | } 53 | 54 | void msg_conn_destroy(u8 sint, u8 conn_id) 55 | { 56 | sint_disable(sint); 57 | synic_ctl(HV_TEST_DEV_MSG_CONN_DESTROY, 0, 0, conn_id); 58 | } 59 | 60 | void evt_conn_create(u8 sint, u8 vec, u8 conn_id) 61 | { 62 | synic_ctl(HV_TEST_DEV_EVT_CONN_CREATE, smp_id(), sint, conn_id); 63 | sint_enable(sint, vec, true); 64 | } 65 | 66 | void evt_conn_destroy(u8 sint, u8 conn_id) 67 | { 68 | sint_disable(sint); 69 | synic_ctl(HV_TEST_DEV_EVT_CONN_DESTROY, 0, 0, conn_id); 70 | } 71 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/pci-edu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Edu PCI device. 3 | * 4 | * Copyright (C) 2016 Red Hat, Inc. 5 | * 6 | * Authors: 7 | * Peter Xu , 8 | * 9 | * This work is licensed under the terms of the GNU LGPL, version 2 or 10 | * later. 11 | */ 12 | 13 | #include "pci-edu.h" 14 | #include "asm/barrier.h" 15 | 16 | /* Return true if alive */ 17 | static inline bool edu_check_alive(struct pci_edu_dev *dev) 18 | { 19 | static uint32_t live_count = 1; 20 | uint32_t value; 21 | 22 | edu_reg_writel(dev, EDU_REG_ALIVE, live_count++); 23 | value = edu_reg_readl(dev, EDU_REG_ALIVE); 24 | return (live_count - 1 == ~value); 25 | } 26 | 27 | bool edu_init(struct pci_edu_dev *dev) 28 | { 29 | pcidevaddr_t dev_addr; 30 | 31 | dev_addr = pci_find_dev(PCI_VENDOR_ID_QEMU, PCI_DEVICE_ID_EDU); 32 | if (dev_addr == PCIDEVADDR_INVALID) 33 | return false; 34 | 35 | pci_dev_init(&dev->pci_dev, dev_addr); 36 | pci_enable_defaults(&dev->pci_dev); 37 | dev->reg_base = ioremap(dev->pci_dev.resource[EDU_BAR], PAGE_SIZE); 38 | assert(edu_check_alive(dev)); 39 | return true; 40 | } 41 | 42 | void edu_dma(struct pci_edu_dev *dev, iova_t iova, 43 | size_t size, unsigned int dev_offset, bool from_device) 44 | { 45 | uint64_t from, to; 46 | uint32_t cmd = EDU_CMD_DMA_START; 47 | 48 | assert(size <= EDU_DMA_SIZE_MAX); 49 | assert(dev_offset < EDU_DMA_SIZE_MAX); 50 | 51 | printf("edu device DMA start %s addr %#" PRIx64 " size %lu off %#x\n", 52 | from_device ? "FROM" : "TO", 53 | iova, (ulong)size, dev_offset); 54 | 55 | if (from_device) { 56 | from = dev_offset + EDU_DMA_START; 57 | to = iova; 58 | cmd |= EDU_CMD_DMA_FROM; 59 | } else { 60 | from = iova; 61 | to = EDU_DMA_START + dev_offset; 62 | cmd |= EDU_CMD_DMA_TO; 63 | } 64 | 65 | edu_reg_writeq(dev, EDU_REG_DMA_SRC, from); 66 | edu_reg_writeq(dev, EDU_REG_DMA_DST, to); 67 | edu_reg_writeq(dev, EDU_REG_DMA_COUNT, size); 68 | edu_reg_writel(dev, EDU_REG_DMA_CMD, cmd); 69 | 70 | /* Wait until DMA finished */ 71 | while (edu_reg_readl(dev, EDU_REG_DMA_CMD) & EDU_CMD_DMA_START) 72 | cpu_relax(); 73 | } 74 | -------------------------------------------------------------------------------- /tests/benchmark/arch-python.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | const BENCH_COLLECT_STATS = +process.env.BENCH_COLLECT_STATS; 5 | 6 | const { V86, print_stats } = require(`../../build/${BENCH_COLLECT_STATS ? "libv86-debug" : "libv86"}.js`); 7 | const path = require("path"); 8 | 9 | const V86_ROOT = path.join(__dirname, "../.."); 10 | 11 | const emulator = new V86({ 12 | bios: { url: path.join(V86_ROOT, "/bios/seabios.bin") }, 13 | vga_bios: { url: path.join(V86_ROOT, "/bios/vgabios.bin") }, 14 | autostart: true, 15 | memory_size: 512 * 1024 * 1024, 16 | vga_memory_size: 8 * 1024 * 1024, 17 | network_relay_url: "", 18 | initial_state: { url: path.join(V86_ROOT, "/images/arch_state.bin") }, 19 | filesystem: { baseurl: path.join(V86_ROOT, "/images/arch-nongz/") }, 20 | screen_dummy: true, 21 | disable_jit: +process.env.DISABLE_JIT, 22 | log_level: 0, 23 | }); 24 | 25 | emulator.bus.register("emulator-started", function() 26 | { 27 | emulator.create_file("/bench.py", Buffer.from(` 28 | def fib(n): 29 | if n < 2: 30 | return n 31 | return fib(n-2) + fib(n-1) 32 | 33 | n = 30 34 | print("fib(", n, ")= ", fib(n)) 35 | `)); 36 | 37 | setTimeout(() => { 38 | emulator.serial0_send(`python3 /bench.py > /dev/null && python /bench.py > /dev/null && time python /bench.py\n`); 39 | }, 1000); 40 | }); 41 | 42 | var line = ""; 43 | 44 | emulator.add_listener("serial0-output-byte", function(byte) 45 | { 46 | var chr = String.fromCharCode(byte); 47 | if(chr < " " && chr !== "\n" && chr !== "\t" || chr > "~") 48 | { 49 | return; 50 | } 51 | 52 | if(chr === "\n") 53 | { 54 | console.log("%s", line); 55 | 56 | if(line.startsWith("sys")) 57 | { 58 | emulator.stop(); 59 | 60 | if(BENCH_COLLECT_STATS) 61 | { 62 | const cpu = emulator.v86.cpu; 63 | console.log(print_stats.stats_to_string(cpu)); 64 | } 65 | } 66 | 67 | line = ""; 68 | } 69 | else 70 | { 71 | line += chr; 72 | } 73 | }); 74 | --------------------------------------------------------------------------------