diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 00000000..fcd33554 --- /dev/null +++ b/.cargo/config @@ -0,0 +1,2 @@ +[build] +target-dir = "build" diff --git a/.gitignore b/.gitignore index 8fa051f9..0b942c8a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,27 @@ *.swp *.swo -deploy.sh -screenshots/ tests/qemu/test-i386 +tests/jit-paging/test-jit *.map build/ closure-compiler/ images/ *.bak *.orig +*.wasm *.o *.bin *.img *.fixture *.fuse_hidden* *.DS_Store +node_modules/ +Cargo.lock +build-head +src/rust/gen/interpreter.rs +src/rust/gen/interpreter0f.rs +src/rust/gen/analyzer.rs +src/rust/gen/analyzer0f.rs +src/rust/gen/jit.rs +src/rust/gen/jit0f.rs +bios/seabios diff --git a/.jshint.json b/.jshint.json new file mode 100644 index 00000000..ac873d6a --- /dev/null +++ b/.jshint.json @@ -0,0 +1,25 @@ +{ + "esversion": 8, + "globalstrict": true, + "sub": true, + "expr": true, + "-W058": true, + "-W080": true, + "-W082": true, + "-W079": true, + "-W117": true, + "-W054": true, + "-W027": true, + "-W040": true, + "-W087": true, + "-W008": true, + "loopfunc": true, + "shadow": true, + "funcscope": true, + "globals": { + "Blob": false, + "alert": false, + "console": false + }, + "browser": true +} diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 00000000..6c4973cb --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,9 @@ +use_field_init_shorthand = true +match_block_trailing_comma = true +fn_single_line = true +imports_indent = "Block" +control_brace_style = "ClosingNextLine" +single_line_if_else_max_width = 92 +ignore = [ + "src/rust/gen" +] diff --git a/.travis-run-integration-acpi.sh b/.travis-run-integration-acpi.sh deleted file mode 100755 index ec59b47a..00000000 --- a/.travis-run-integration-acpi.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -set -e -mkdir -p images -(cd images && curl --compressed -OOOOOOOOOO https://copy.sh/v86/images/{linux.iso,linux3.iso,kolibri.img,windows101.img,os8.dsk,freedos722.img,openbsd.img,oberon.dsk,oberon-boot.dsk}) -make build/libv86.js useacpi=true -tests/full/run.js diff --git a/.travis-run-integration.sh b/.travis-run-integration.sh deleted file mode 100755 index 58ef8d36..00000000 --- a/.travis-run-integration.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -set -e -mkdir -p images -(cd images && curl --compressed -OOOOOOOOOO https://copy.sh/v86/images/{linux.iso,linux3.iso,kolibri.img,windows101.img,os8.dsk,freedos722.img,openbsd.img,oberon.dsk,oberon-boot.dsk}) -make build/libv86.js -tests/full/run.js diff --git a/.travis-run-nasm.sh b/.travis-run-nasm.sh deleted file mode 100755 index 37970232..00000000 --- a/.travis-run-nasm.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash -set -e -make nasmtests diff --git a/.travis-run-unit-qemu.sh b/.travis-run-unit-qemu.sh deleted file mode 100755 index da3e93f2..00000000 --- a/.travis-run-unit-qemu.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -e -mkdir -p images -(cd images && curl --compressed -O https://copy.sh/v86/images/linux3.iso) -make qemutests diff --git a/.travis-run-unit.sh b/.travis-run-unit.sh deleted file mode 100755 index 3e60572a..00000000 --- a/.travis-run-unit.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -e -make build/libv86.js -(cd tests/kvm-unit-tests && ./configure && make) -tests/kvm-unit-tests/run.js tests/kvm-unit-tests/x86/realmode.flat diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3da4270c..00000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -language: node_js -node_js: - - "6.10.2" -dist: trusty -before_install: - - sudo dpkg --add-architecture i386 - - sudo apt-get update -qq -install: - - sudo apt-get install -y gcc-multilib nasm gdb -script: - - "./.travis-run-$TEST_SUITE.sh" -env: - - TEST_SUITE=unit - - TEST_SUITE=integration - - TEST_SUITE=integration-acpi - - TEST_SUITE=unit-qemu - - TEST_SUITE=nasm -matrix: - allow_failures: - - env: TEST_SUITE=unit-qemu diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000..6e92b93f --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "v86" +version = "0.1.0" +publish = false + +[dev-dependencies] +quickcheck = "0.6.2" + +[features] +default = [] +profiler = [] + +[lib] +crate-type = ["cdylib"] +path = "src/rust/lib.rs" + +[profile.dev] +lto = false +opt-level = 2 +panic = "abort" +overflow-checks = false + +[profile.release] +lto = true +opt-level = 3 +incremental = false +panic = "abort" diff --git a/LICENSE b/LICENSE index 753ff9d8..5033d6de 100644 --- a/LICENSE +++ b/LICENSE @@ -1,14 +1,14 @@ -Copyright (c) 2012-2018, Fabian Hemmer +Copyright (c) 2012, The v86 contributors All rights reserved. Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. + list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. + and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -20,7 +20,3 @@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those -of the authors and should not be interpreted as representing official policies, -either expressed or implied, of the FreeBSD Project. diff --git a/Makefile b/Makefile index 757ba786..16215e7f 100644 --- a/Makefile +++ b/Makefile @@ -1,44 +1,40 @@ CLOSURE_DIR=closure-compiler CLOSURE=$(CLOSURE_DIR)/compiler.jar -BROWSER=chromium NASM_TEST_DIR=./tests/nasm -all: build/v86_all.js -browser: build/v86_all.js +INSTRUCTION_TABLES=src/rust/gen/jit.rs src/rust/gen/jit0f.rs \ + src/rust/gen/interpreter.rs src/rust/gen/interpreter0f.rs \ + src/rust/gen/analyzer.rs src/rust/gen/analyzer0f.rs \ -ACPI=false -ifeq ($(useacpi),true) -ACPI=true +# Only the dependencies common to both generate_{jit,interpreter}.js +GEN_DEPENDENCIES=$(filter-out gen/generate_interpreter.js gen/generate_jit.js gen/generate_analyzer.js, $(wildcard gen/*.js)) +JIT_DEPENDENCIES=$(GEN_DEPENDENCIES) gen/generate_jit.js +INTERPRETER_DEPENDENCIES=$(GEN_DEPENDENCIES) gen/generate_interpreter.js +ANALYZER_DEPENDENCIES=$(GEN_DEPENDENCIES) gen/generate_analyzer.js + +STRIP_DEBUG_FLAG= +ifeq ($(STRIP_DEBUG),true) +STRIP_DEBUG_FLAG=--v86-strip-debug endif +default: build/v86-debug.wasm +all: build/v86_all.js build/libv86.js build/v86.wasm +all-debug: build/libv86-debug.js build/v86-debug.wasm +browser: build/v86_all.js + # Used for nodejs builds and in order to profile code. # `debug` gives identifiers a readable name, make sure it doesn't have any side effects. CLOSURE_READABLE=--formatting PRETTY_PRINT --debug CLOSURE_SOURCE_MAP=\ --source_map_format V3\ - --source_map_include_content\ --create_source_map '%outname%.map' - #--jscomp_error reportUnknownTypes\ - #--jscomp_error unusedLocalVariables\ - #--jscomp_error unusedPrivateMembers\ - #--new_type_inf\ - - # Easily breaks code: - #--assume_function_wrapper\ - - # implies new type inferrence - #--jscomp_error newCheckTypes\ - CLOSURE_FLAGS=\ - --js lib/closure-base.js\ --generate_exports\ --externs src/externs.js\ --warning_level VERBOSE\ --jscomp_error accessControls\ - --jscomp_error ambiguousFunctionDecl\ - --jscomp_error checkEventfulObjectDisposal\ --jscomp_error checkRegExp\ --jscomp_error checkTypes\ --jscomp_error checkVars\ @@ -48,15 +44,11 @@ CLOSURE_FLAGS=\ --jscomp_error deprecated\ --jscomp_error deprecatedAnnotations\ --jscomp_error duplicateMessage\ - --jscomp_error es3\ --jscomp_error es5Strict\ --jscomp_error externsValidation\ - --jscomp_error fileoverviewTags\ --jscomp_error globalThis\ - --jscomp_error internetExplorerChecks\ --jscomp_error invalidCasts\ --jscomp_error misplacedTypeAnnotation\ - --jscomp_error missingGetCssName\ --jscomp_error missingProperties\ --jscomp_error missingReturn\ --jscomp_error msgDescriptions\ @@ -70,22 +62,35 @@ CLOSURE_FLAGS=\ --jscomp_error visibility\ --use_types_for_optimization\ --summary_detail_level 3\ - --language_in ECMASCRIPT5_STRICT + --language_in ECMASCRIPT_2017\ + --language_out ECMASCRIPT_2017 -TRANSPILE_ES6_FLAGS=\ - --language_in ECMASCRIPT6_STRICT\ - --language_out ECMASCRIPT5_STRICT\ +CARGO_FLAGS_SAFE=\ + --target wasm32-unknown-unknown \ + -- \ + -C linker=tools/rust-lld-wrapper \ + -C link-args="--import-table --global-base=262144 $(STRIP_DEBUG_FLAG)" \ + -C link-args="build/softfloat.o" \ + -C link-args="build/zstddeclib.o" \ + --verbose +CARGO_FLAGS=$(CARGO_FLAGS_SAFE) -C target-feature=+bulk-memory -CORE_FILES=const.js config.js io.js main.js lib.js fpu.js ide.js pci.js floppy.js memory.js \ - dma.js pit.js vga.js ps2.js pic.js rtc.js uart.js hpet.js acpi.js apic.js ioapic.js \ +CORE_FILES=const.js config.js io.js main.js lib.js ide.js pci.js floppy.js \ + memory.js dma.js pit.js vga.js ps2.js pic.js rtc.js uart.js hpet.js \ + acpi.js apic.js ioapic.js \ state.js ne2k.js sb16.js virtio.js bus.js log.js \ - cpu.js translate.js modrm.js string.js arith.js misc_instr.js instructions.js debug.js \ - elf.js + cpu.js debug.js \ + elf.js kernel.js LIB_FILES=9p.js filesystem.js jor1k.js marshall.js utf8.js -BROWSER_FILES=screen.js \ - keyboard.js mouse.js speaker.js serial.js \ - network.js lib.js starter.js worker_bus.js dummy_screen.js +BROWSER_FILES=screen.js keyboard.js mouse.js speaker.js serial.js \ + network.js lib.js starter.js worker_bus.js dummy_screen.js \ + print_stats.js filestorage.js + +RUST_FILES=$(shell find src/rust/ -name '*.rs') \ + src/rust/gen/interpreter.rs src/rust/gen/interpreter0f.rs \ + src/rust/gen/jit.rs src/rust/gen/jit0f.rs \ + src/rust/gen/analyzer.rs src/rust/gen/analyzer0f.rs CORE_FILES:=$(addprefix src/,$(CORE_FILES)) LIB_FILES:=$(addprefix lib/,$(LIB_FILES)) @@ -97,20 +102,27 @@ build/v86_all.js: $(CLOSURE) src/*.js src/browser/*.js lib/*.js java -jar $(CLOSURE) \ --js_output_file build/v86_all.js\ --define=DEBUG=false\ - --define=ENABLE_ACPI=$(ACPI)\ $(CLOSURE_SOURCE_MAP)\ $(CLOSURE_FLAGS)\ --compilation_level ADVANCED\ - $(TRANSPILE_ES6_FLAGS)\ --js $(CORE_FILES)\ --js $(LIB_FILES)\ --js $(BROWSER_FILES)\ --js src/browser/main.js - - echo '//# sourceMappingURL=v86_all.js.map' >> build/v86_all.js - ls -lh build/v86_all.js +build/v86_all_debug.js: $(CLOSURE) src/*.js src/browser/*.js lib/*.js + mkdir -p build + java -jar $(CLOSURE) \ + --js_output_file build/v86_all_debug.js\ + --define=DEBUG=true\ + $(CLOSURE_SOURCE_MAP)\ + $(CLOSURE_FLAGS)\ + --compilation_level ADVANCED\ + --js $(CORE_FILES)\ + --js $(LIB_FILES)\ + --js $(BROWSER_FILES)\ + --js src/browser/main.js build/libv86.js: $(CLOSURE) src/*.js lib/*.js src/browser/*.js mkdir -p build @@ -118,62 +130,209 @@ build/libv86.js: $(CLOSURE) src/*.js lib/*.js src/browser/*.js java -jar $(CLOSURE) \ --js_output_file build/libv86.js\ --define=DEBUG=false\ - --define=ENABLE_ACPI=$(ACPI)\ - $(CLOSURE_SOURCE_MAP)\ $(CLOSURE_FLAGS)\ --compilation_level SIMPLE\ - $(TRANSPILE_ES6_FLAGS)\ + --output_wrapper ';(function(){%output%}).call(this);'\ + --js $(CORE_FILES)\ + --js $(BROWSER_FILES)\ + --js $(LIB_FILES) + ls -lh build/libv86.js + +build/libv86-debug.js: $(CLOSURE) src/*.js lib/*.js src/browser/*.js + mkdir -p build + java -jar $(CLOSURE) \ + --js_output_file build/libv86-debug.js\ + --define=DEBUG=true\ + $(CLOSURE_FLAGS)\ + $(CLOSURE_READABLE)\ + --compilation_level SIMPLE\ --output_wrapper ';(function(){%output%}).call(this);'\ --js $(CORE_FILES)\ --js $(BROWSER_FILES)\ --js $(LIB_FILES) - echo '//# sourceMappingURL=libv86.js.map' >> build/libv86.js +src/rust/gen/jit.rs: $(JIT_DEPENDENCIES) + ./gen/generate_jit.js --output-dir build/ --table jit +src/rust/gen/jit0f.rs: $(JIT_DEPENDENCIES) + ./gen/generate_jit.js --output-dir build/ --table jit0f - ls -lh build/libv86.js +src/rust/gen/interpreter.rs: $(INTERPRETER_DEPENDENCIES) + ./gen/generate_interpreter.js --output-dir build/ --table interpreter +src/rust/gen/interpreter0f.rs: $(INTERPRETER_DEPENDENCIES) + ./gen/generate_interpreter.js --output-dir build/ --table interpreter0f + +src/rust/gen/analyzer.rs: $(ANALYZER_DEPENDENCIES) + ./gen/generate_analyzer.js --output-dir build/ --table analyzer +src/rust/gen/analyzer0f.rs: $(ANALYZER_DEPENDENCIES) + ./gen/generate_analyzer.js --output-dir build/ --table analyzer0f + +build/v86.wasm: $(RUST_FILES) build/softfloat.o build/zstddeclib.o Cargo.toml + mkdir -p build/ + -ls -lh build/v86.wasm + cargo +nightly rustc --release $(CARGO_FLAGS) + mv build/wasm32-unknown-unknown/release/v86.wasm build/v86.wasm + ls -lh build/v86.wasm + +build/v86-debug.wasm: $(RUST_FILES) build/softfloat.o build/zstddeclib.o Cargo.toml + mkdir -p build/ + -ls -lh build/v86-debug.wasm + cargo +nightly rustc $(CARGO_FLAGS) + mv build/wasm32-unknown-unknown/debug/v86.wasm build/v86-debug.wasm + ls -lh build/v86-debug.wasm + +build/v86-fallback.wasm: $(RUST_FILES) build/softfloat.o build/zstddeclib.o Cargo.toml + mkdir -p build/ + cargo +nightly rustc --release $(CARGO_FLAGS_SAFE) + mv build/wasm32-unknown-unknown/release/v86.wasm build/v86-fallback.wasm || true + +debug-with-profiler: $(RUST_FILES) build/softfloat.o build/zstddeclib.o Cargo.toml + mkdir -p build/ + cargo +nightly rustc --features profiler $(CARGO_FLAGS) + mv build/wasm32-unknown-unknown/debug/v86.wasm build/v86-debug.wasm || true + +with-profiler: $(RUST_FILES) build/softfloat.o build/zstddeclib.o Cargo.toml + mkdir -p build/ + cargo +nightly rustc --release --features profiler $(CARGO_FLAGS) + mv build/wasm32-unknown-unknown/release/v86.wasm build/v86.wasm || true + +build/softfloat.o: lib/softfloat/softfloat.c + mkdir -p build + clang -c -Wall \ + --target=wasm32 -O3 -flto -nostdlib -fvisibility=hidden -ffunction-sections -fdata-sections \ + -DSOFTFLOAT_FAST_INT64 -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV32TO16 -DSOFTFLOAT_FAST_DIV64TO32 \ + -o build/softfloat.o \ + lib/softfloat/softfloat.c + +build/zstddeclib.o: lib/zstd/zstddeclib.c + mkdir -p build + clang -c -Wall \ + --target=wasm32 -O3 -flto -nostdlib -fvisibility=hidden -ffunction-sections -fdata-sections \ + -I /usr/include \ + -o build/zstddeclib.o \ + lib/zstd/zstddeclib.c clean: -rm build/libv86.js + -rm build/libv86-debug.js -rm build/v86_all.js - -rm build/libv86.js.map - -rm build/v86_all.js.map + -rm build/v86.wasm + -rm build/v86-debug.wasm + -rm $(INSTRUCTION_TABLES) + -rm build/*.map + -rm build/*.wast + -rm build/*.o $(MAKE) -C $(NASM_TEST_DIR) clean run: python3 -m http.server 2> /dev/null - #sleep 1 - #$(BROWSER) http://localhost:8000/index.html & update_version: set -e ;\ COMMIT=`git log --format="%h" -n 1` ;\ DATE=`git log --date="format:%b %e, %Y %H:%m" --format="%cd" -n 1` ;\ - SEARCH='Version: [a-f0-9]\+ ([^(]\+)' ;\ - REPLACE='Version: '$$COMMIT' ('$$DATE')' ;\ + SEARCH='Version: [a-f0-9]\+ ([^(]\+)' ;\ + REPLACE='Version: '$$COMMIT' ('$$DATE')' ;\ sed -i "s@$$SEARCH@$$REPLACE@g" index.html ;\ grep $$COMMIT index.html $(CLOSURE): - wget -P $(CLOSURE_DIR) https://dl.google.com/closure-compiler/compiler-20190709.zip - unzip -d closure-compiler $(CLOSURE_DIR)/compiler-20190709.zip \*.jar - mv $(CLOSURE_DIR)/*.jar $(CLOSURE) - rm $(CLOSURE_DIR)/compiler-20190709.zip + mkdir -p $(CLOSURE_DIR) + wget -nv -O $(CLOSURE) https://repo1.maven.org/maven2/com/google/javascript/closure-compiler/v20201207/closure-compiler-v20201207.jar -tests: build/libv86.js +build/integration-test-fs/fs.json: + mkdir -p build/integration-test-fs/flat + cp images/buildroot-bzimage.bin build/integration-test-fs/bzImage + touch build/integration-test-fs/initrd + cd build/integration-test-fs && tar cfv fs.tar bzImage initrd + ./tools/fs2json.py build/integration-test-fs/fs.tar --out build/integration-test-fs/fs.json + ./tools/copy-to-sha256.py build/integration-test-fs/fs.tar build/integration-test-fs/flat + rm build/integration-test-fs/fs.tar build/integration-test-fs/bzImage build/integration-test-fs/initrd + +tests: all-debug build/integration-test-fs/fs.json ./tests/full/run.js -nasmtests: build/libv86.js +tests-release: all build/integration-test-fs/fs.json + TEST_RELEASE_BUILD=1 ./tests/full/run.js + +nasmtests: all-debug $(MAKE) -C $(NASM_TEST_DIR) all + $(NASM_TEST_DIR)/gen_fixtures.js $(NASM_TEST_DIR)/run.js -qemutests: build/libv86.js - make -C tests/qemu test-i386 - ./tests/qemu/run.js > result - ./tests/qemu/test-i386 > reference - diff result reference +nasmtests-force-jit: all-debug + $(MAKE) -C $(NASM_TEST_DIR) all + $(NASM_TEST_DIR)/gen_fixtures.js + $(NASM_TEST_DIR)/run.js --force-jit -kvm-unit-test: build/libv86.js - (cd tests/kvm-unit-tests && ./configure) - make -C tests/kvm-unit-tests +jitpagingtests: all-debug + $(MAKE) -C tests/jit-paging test-jit + ./tests/jit-paging/run.js + +qemutests: all-debug + $(MAKE) -C tests/qemu test-i386 + ./tests/qemu/run.js > build/qemu-test-result + ./tests/qemu/run-qemu.js > build/qemu-test-reference + diff build/qemu-test-result build/qemu-test-reference + +qemutests-release: all + $(MAKE) -C tests/qemu test-i386 + time TEST_RELEASE_BUILD=1 ./tests/qemu/run.js > build/qemu-test-result + ./tests/qemu/run-qemu.js > build/qemu-test-reference + diff build/qemu-test-result build/qemu-test-reference + +kvm-unit-test: all-debug + (cd tests/kvm-unit-tests && ./configure && make) tests/kvm-unit-tests/run.js tests/kvm-unit-tests/x86/realmode.flat + +kvm-unit-test-release: all + (cd tests/kvm-unit-tests && ./configure && make) + TEST_RELEASE_BUILD=1 tests/kvm-unit-tests/run.js tests/kvm-unit-tests/x86/realmode.flat + +expect-tests: all-debug build/libwabt.js + make -C tests/expect/tests + ./tests/expect/run.js + +devices-test: all-debug + ./tests/devices/virtio_9p.js + +rust-test: $(RUST_FILES) + # RUSTFLAGS="-D warnings" + env RUST_BACKTRACE=full RUST_TEST_THREADS=1 cargo +nightly test -- --nocapture + ./tests/rust/verify-wasmgen-dummy-output.js + +rust-no-warnings: + RUSTFLAGS="-D warnings" make all all-debug + +rust-test-intensive: + QUICKCHECK_TESTS=100000000 make rust-test + +api-tests: all-debug + ./tests/api/clean-shutdown.js + ./tests/api/state.js + ./tests/api/reset.js + +all-tests: jshint kvm-unit-test qemutests qemutests-release jitpagingtests api-tests nasmtests nasmtests-force-jit tests expect-tests + # Skipping: + # - devices-test (hangs) + +jshint: + jshint --config=./.jshint.json src tests gen lib --exclude lib/closure-base.js + +rustfmt: $(RUST_FILES) + cargo +nightly fmt --all -- --check + +build/capstone-x86.min.js: + mkdir -p build + wget -P build https://github.com/AlexAltea/capstone.js/releases/download/v3.0.5-rc1/capstone-x86.min.js + +build/libwabt.js: + mkdir -p build + wget -P build https://github.com/WebAssembly/wabt/archive/1.0.6.zip + unzip -j -d build/ build/1.0.6.zip wabt-1.0.6/demo/libwabt.js + rm build/1.0.6.zip + +build/xterm.js: + curl https://cdn.jsdelivr.net/npm/xterm@4.2.0-vscode1/lib/xterm.js > build/xterm.js + curl https://cdn.jsdelivr.net/npm/xterm@4.2.0-vscode1/lib/xterm.js.map > build/xterm.js.map + curl https://cdn.jsdelivr.net/npm/xterm@4.2.0-vscode1/css/xterm.css > build/xterm.css diff --git a/Readme.md b/Readme.md index 9f8ffe78..ed1dff28 100644 --- a/Readme.md +++ b/Readme.md @@ -1,16 +1,126 @@ [![Join the chat at https://gitter.im/copy/v86](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/copy/v86) +v86 emulates an x86-compatible CPU and hardware. Machine code is translated to +WebAssembly modules at runtime in order to achieve decent performance. Here's a +list of emulated hardware: + +- An x86-compatible CPU. The instruction set is around Pentium III level, + including full SSE2 support. Some features are missing, in particular: + - Task gates, far calls in protected mode + - Some 16 bit protected mode features + - Single stepping (trap flag, debug registers) + - Some exceptions, especially floating point and SSE + - Multicore + - PAE + - 64-bit extensions +- A floating point unit (FPU). Calculations are done using the Berkeley + SoftFloat library and therefore should be precise (but slow). Trigonometric + and log functions are emulated using 64-bit floats and may be less precise. + Not all FPU excpetions are supported. +- A floppy disk controller (8272A). +- An 8042 Keyboard Controller, PS2. With mouse support. +- An 8254 Programmable Interval Timer (PIT). +- An 8259 Programmable Interrupt Controller (PIC). +- Partial APIC support. +- A CMOS Real Time Clock (RTC). +- A generic VGA card with SVGA support and Bochs VBE Extensions. +- A PCI bus. This one is partly incomplete and not used by every device. +- An IDE disk controller. +- An NE2000 (8390) PCI network card. +- A virtio filesystem. +- A SoundBlaster 16 sound card. Demos - -- [Windows 98](https://copy.sh/v86/?profile=windows98) -- [Linux](https://copy.sh/v86/?profile=linux26) -- [Linux 3](https://copy.sh/v86/?profile=linux3) -- [KolibriOS](https://copy.sh/v86/?profile=kolibrios) -- [FreeDOS](https://copy.sh/v86/?profile=freedos) -- [Windows 1.01](https://copy.sh/v86/?profile=windows1) -- [Archlinux](https://copy.sh/v86/?profile=archlinux) +[Arch Linux](https://copy.sh/v86/?profile=archlinux) — +[Damn Small Linux](https://copy.sh/v86/?profile=dsl) — +[Buildroot Linux](https://copy.sh/v86/?profile=buildroot) — +[ReactOS](https://copy.sh/v86/?profile=reactos) — +[Windows 98](https://copy.sh/v86/?profile=windows98) — +[Windows 95](https://copy.sh/v86/?profile=windows95) — +[Windows 1.01](https://copy.sh/v86/?profile=windows1) — +[MS-DOS](https://copy.sh/v86/?profile=msdos) — +[FreeDOS](https://copy.sh/v86/?profile=freedos) — +[FreeBSD](https://copy.sh/v86/?profile=freebsd) — +[OpenBSD](https://copy.sh/v86/?profile=openbsd) — +[9front](https://copy.sh/v86/?profile=9front) — +[Haiku](https://copy.sh/v86/?profile=haiku) — +[Oberon](https://copy.sh/v86/?profile=oberon) — +[KolibriOS](https://copy.sh/v86/?profile=kolibrios) — +[QNX](https://copy.sh/v86/?profile=qnx) + + +Compatibility +- + +Here's an overview of the operating systems supported in v86: + +- Linux works pretty well. Neither 64-bit nor PAE kernels are supported. + - Damn Small Linux (2.4 Kernel) works. + - All tested versions of TinyCore work. + - [BuildRoot](https://buildroot.uclibc.org) can be used to build a minimal + image. [humphd/browser-vm](https://github.com/humphd/browser-vm) has some + useful scripts for building one. + - Archlinux works. See [archlinux.md](docs/archlinux.md) for building an image. + - Debian works. An image can be built from a Dockerfile, see [tools/docker/debian/](tools/docker/debian/). + - Alpine Linux works. +- ReactOS works. +- FreeDOS, Windows 1.01 and MS-DOS run very well. +- KolibriOS works. +- Haiku works. +- Android x86 1.6-r2 works if one selects VESA mode at the boot prompt. Newer + versions haven't been tested. +- Windows 1, 3.0, 95, 98 and ME work. Other versions currently don't (see #86, #208). +- Many hobby operating systems work. +- 9front works. +- Plan 9 doesn't work. +- QNX works. +- OS/2 doesn't work. +- FreeBSD works. +- OpenBSD works with a specific boot configuration. At the `boot>` prompt type + `boot -c`, then at the `UKC>` prompt `disable mpbios` and `exit`. +- NetBSD works only with a custom kernel, see #350. +- SerenityOS doesn't work due to missing PAE support. + +You can get some infos on the disk images here: https://github.com/copy/images. + +How to build, run and embed? +- + +You need: + +- java (for Closure Compiler, not necessary when using `debug.html`) +- make +- gcc and libc-i386 for building some of the test binaries +- nasm, gdb and qemu-system (for running tests) +- rust-nightly with the wasm32-unknown-unknown target +- A version of clang compatible with rust-nightly +- nodejs (a recent version is required, 10.11.0 is known to be working) + +See `tools/docker/test-image/Dockerfile` for a full setup on Debian. + + +- Run `make` to build the debug build (at `debug.html`). +- Run `make all` to build the optimized build (at `index.html`). +- ROM and disk images are loaded via XHR, so if you want to try out `index.html` + locally, make sure to serve it from a local webserver. You can use `make run` + to serve the files using Python's http module. +- If you only want to embed v86 in a webpage you can use libv86.js. For + usage, check out the [examples](examples/). + + +Testing +- + +The disk images for testing are not included in this repository. You can +download them directly from the website using: + +`wget -P images/ https://k.copy.sh/{linux.iso,linux4.iso,buildroot-bzimage.bin,openbsd-floppy.img,kolibri.img,windows101.img,os8.img,freedos722.img}` + +Run all tests: `make jshint rustfmt kvm-unit-test nasmtests nasmtests-force-jit expect-tests jitpagingtests qemutests rust-test tests` + +See [tests/Readme.md](tests/Readme.md) for more infos. API examples @@ -40,131 +150,29 @@ var emulator = new V86Starter({ }); ``` -See [API](docs/api.md). +See [starter.js](src/browser/starter.js). -How does it work? -- - -v86 emulates an x86-compatible CPU and hardware. Here's a list of emulated hardware: - -- An x86 compatible CPU. The instruction set is around Pentium 1 level. Some - features are missing, more specifically: - - Task gates, far calls in protected mode - - 16 bit protected mode features - - Single stepping - - MMX, SSE - - A bunch of FPU instructions - - Some exceptions -- A floating point unit (FPU). Calculations are done with JavaScript's double - precision numbers (64 bit), so they are not as precise as calculations on a - real FPU (80 bit). -- A floppy disk controller (8272A). -- An 8042 Keyboard Controller, PS2. With mouse support. -- An 8254 Programmable Interval Timer (PIT). -- An 8259 Programmable Interrupt Controller (PIC). -- A CMOS Real Time Clock (RTC). -- A generic VGA card with SVGA support and Bochs VBE Extensions. -- A PCI bus. This one is partly incomplete and not used by every device. -- An IDE disk controller. -- An NE2000 (8390) PCI network card. -- A virtio filesystem. -- A SoundBlaster 16 sound card. - - -Testing -- - -The disk images are not included in this repository. You can download them -directly from the website using: - -`wget -P images/ https://copy.sh/v86/images/{linux.iso,linux3.iso,kolibri.img,windows101.img,os8.dsk,freedos722.img,openbsd.img}`. - -A testsuite is available in `tests/full/`. Run it using `node tests/full/run.js`. - - -How to build, run and embed? -- - -- Building is only necessary for releases, open debug.html and everything should load out of the box -- If you want a compressed and fast (i.e. with debug code removed) version, you - need Closure Compiler. Download it as shown below and run `make build/v86_all.js`. -- ROM and disk images are loaded via XHR, so if you want to try out `index.html` - locally, make sure to serve it from a local webserver. You can use `make run` - to serve the files using Python's SimpleHTTPServer. -- If you only want to embed v86 in a webpage you can use libv86.js. For - usage, check out the [API](docs/api.md) and [examples](examples/). -- A couple of disk images are provided for testing. You can check them out - using `wget -P images/ https://copy.sh/v86/images/{linux.iso,linux3.iso,kolibri.img,windows101.img,os8.dsk,freedos722.img,openbsd.img}`. - - -**Short summary:** - -```bash -# grab the main repo -git clone https://github.com/copy/v86.git && cd v86 - -# grab the disk images -wget -P images/ https://copy.sh/v86/images/{linux.iso,linux3.iso,kolibri.img,windows101.img,os8.dsk,freedos722.img,openbsd.img} - -# grab closure compiler -wget -P closure-compiler https://dl.google.com/closure-compiler/compiler-latest.zip -unzip -d closure-compiler closure-compiler/compiler-latest.zip *.jar - -# build the library -make build/libv86.js - -# run the tests -./tests/full/run.js -``` - -Compatibility -- - -Here's an overview of the operating systems supported in v86: - -- Linux works pretty well. - - Tinycore (3.16, 4.8 kernel): Works. - - Nanolinux works. - - Archlinux works with some caveats. See [archlinux.md](docs/archlinux.md). - - Damn Small Linux (2.4 Kernel): Doesn't work. -- ReactOS works. -- FreeDOS, Windows 1.01 and MS-DOS run very well. -- KolibriOS works. A few applications need SSE. -- Haiku boots, but takes very long (around 30 minutes). -- No Android version seems to work, you still get a shell. -- Windows 1, 3, 95 and 98 work. Windows XP is unstable, but can work with some - tweaks ([see this issue](https://github.com/copy/v86/issues/86)). Other - versions might work but haven't been tested. -- Many hobby operating systems work. -- FreeBSD works. -- OS/2 doesn't work. - -You can get some infos on the disk images here: https://github.com/copy/images. -The Windows images are from [WinWorld](https://winworldpc.com/). - - -How can I contribute? -- - -- Add new features (hardware devices, fill holes in the CPU), fix bugs. Check - out the issues section and contact me if you need help. -- Report bugs. -- If you want to donate, let me know. - License - -- Source code and most tests: Simplified BSD License, see [LICENSE](LICENSE). -- QEMU test suite: See [tests/qemu/LICENSE](LICENSE). +v86 is distributed under the terms of the Simplified BSD License, see +[LICENSE](LICENSE). The following third-party dependencies are included in the +repository under their own licenses: + +- [`lib/softfloat/softfloat.c`](lib/softfloat/softfloat.c) +- [`lib/zstd/zstddeclib.c`](lib/zstd/zstddeclib.c) +- [`tests/kvm-unit-tests/`](tests/kvm-unit-tests) +- [`tests/qemutests/`](tests/qemutests) Credits - -- CPU test cases via QEMU, http://wiki.qemu.org/Main_Page +- CPU test cases via [QEMU](https://wiki.qemu.org/Main_Page) - More tests via [kvm-unit-tests](https://www.linux-kvm.org/page/KVM-unit-tests) -- [Disk Images](https://github.com/copy/images) +- [zstd](https://github.com/facebook/zstd) support is included for better compression of state images +- [Berkeley SoftFloat](http://www.jhauser.us/arithmetic/SoftFloat.html) is included to precisely emulate 80-bit floating point numbers - [The jor1k project](https://github.com/s-macke/jor1k) for 9p, filesystem and uart drivers - [WinWorld](https://winworldpc.com/) sources of some old operating systems @@ -172,11 +180,10 @@ Credits More questions? - -Shoot me an email to `copy@copy.sh`. Please don't tell about bugs via mail, -create a bug report on GitHub instead. +Shoot me an email to `copy@copy.sh`. Please report bugs on GitHub. Author - -Fabian Hemmer (http://copy.sh/, `copy@copy.sh`) +Fabian Hemmer (https://copy.sh/, `copy@copy.sh`) diff --git a/bios/fetch-and-build-seabios.sh b/bios/fetch-and-build-seabios.sh new file mode 100755 index 00000000..3624fe24 --- /dev/null +++ b/bios/fetch-and-build-seabios.sh @@ -0,0 +1,13 @@ +set -e +git clone https://git.seabios.org/seabios.git || true +(cd seabios && git checkout rel-1.12.1) + +cp seabios.config seabios/.config +make -C seabios +cp seabios/out/bios.bin seabios.bin +cp seabios/out/vgabios.bin vgabios.bin + +cp seabios-debug.config seabios/.config +make -C seabios +cp seabios/out/bios.bin seabios-debug.bin +cp seabios/out/vgabios.bin vgabios-debug.bin diff --git a/bios/seabios-debug.bin b/bios/seabios-debug.bin index 8bf81ad1..3a9afb31 100644 Binary files a/bios/seabios-debug.bin and b/bios/seabios-debug.bin differ diff --git a/bios/seabios-debug.config b/bios/seabios-debug.config new file mode 100644 index 00000000..59e4cd77 --- /dev/null +++ b/bios/seabios-debug.config @@ -0,0 +1,117 @@ +# +# Automatically generated file; DO NOT EDIT. +# SeaBIOS Configuration +# + +# +# General Features +# +# CONFIG_COREBOOT is not set +CONFIG_QEMU=y +# CONFIG_CSM is not set +CONFIG_QEMU_HARDWARE=y +CONFIG_XEN=y +CONFIG_THREADS=y +# CONFIG_RELOCATE_INIT is not set +# CONFIG_BOOTMENU is not set +CONFIG_BOOTORDER=y +CONFIG_MULTIBOOT=y +CONFIG_ENTRY_EXTRASTACK=y +CONFIG_MALLOC_UPPERMEMORY=y +CONFIG_ROM_SIZE=0 + +# +# Hardware support +# +CONFIG_ATA=y +CONFIG_ATA_DMA=y +CONFIG_ATA_PIO32=y +CONFIG_AHCI=y +CONFIG_SDCARD=y +CONFIG_VIRTIO_BLK=y +CONFIG_VIRTIO_SCSI=y +CONFIG_PVSCSI=y +CONFIG_ESP_SCSI=y +CONFIG_LSI_SCSI=y +CONFIG_MEGASAS=y +CONFIG_MPT_SCSI=y +CONFIG_FLOPPY=y +CONFIG_FLASH_FLOPPY=y +# CONFIG_NVME is not set +CONFIG_PS2PORT=y +# CONFIG_USB is not set +CONFIG_SERIAL=y +# CONFIG_SERCON is not set +CONFIG_LPT=y +CONFIG_RTC_TIMER=y +CONFIG_HARDWARE_IRQ=y +CONFIG_USE_SMM=y +CONFIG_CALL32_SMM=y +CONFIG_MTRR_INIT=y +CONFIG_PMTIMER=y +CONFIG_TSC_TIMER=y + +# +# BIOS interfaces +# +CONFIG_DRIVES=y +CONFIG_CDROM_BOOT=y +CONFIG_CDROM_EMU=y +CONFIG_PCIBIOS=y +CONFIG_APMBIOS=y +CONFIG_PNPBIOS=y +CONFIG_OPTIONROMS=y +CONFIG_PMM=y +CONFIG_BOOT=y +CONFIG_KEYBOARD=y +CONFIG_KBD_CALL_INT15_4F=y +CONFIG_MOUSE=y +CONFIG_S3_RESUME=y +CONFIG_VGAHOOKS=y +# CONFIG_DISABLE_A20 is not set +# CONFIG_WRITABLE_UPPERMEMORY is not set +CONFIG_TCGBIOS=y + +# +# BIOS Tables +# +CONFIG_PIRTABLE=y +CONFIG_MPTABLE=y +# CONFIG_SMBIOS is not set +CONFIG_ACPI=y +CONFIG_ACPI_DSDT=y +CONFIG_FW_ROMFILE_LOAD=y + +# +# VGA ROM +# +# CONFIG_NO_VGABIOS is not set +# CONFIG_VGA_STANDARD_VGA is not set +# CONFIG_VGA_CIRRUS is not set +CONFIG_VGA_BOCHS=y +# CONFIG_VGA_GEODEGX2 is not set +# CONFIG_VGA_GEODELX is not set +# CONFIG_DISPLAY_BOCHS is not set +# CONFIG_VGA_RAMFB is not set +CONFIG_VGA_BOCHS_STDVGA=y +# CONFIG_VGA_BOCHS_VMWARE is not set +# CONFIG_VGA_BOCHS_QXL is not set +# CONFIG_VGA_BOCHS_VIRTIO is not set +CONFIG_BUILD_VGABIOS=y +CONFIG_VGA_STDVGA_PORTS=y +CONFIG_VGA_FIXUP_ASM=y +CONFIG_VGA_ALLOCATE_EXTRA_STACK=y +CONFIG_VGA_EXTRA_STACK_SIZE=512 +CONFIG_VGA_VBE=y +CONFIG_VGA_PCI=y +CONFIG_OVERRIDE_PCI_ID=y +CONFIG_VGA_VID=0x1234 +CONFIG_VGA_DID=0x1111 + +# +# Debugging +# +CONFIG_DEBUG_LEVEL=8 +# CONFIG_DEBUG_SERIAL is not set +# CONFIG_DEBUG_SERIAL_MMIO is not set +CONFIG_DEBUG_IO=y diff --git a/bios/seabios.bin b/bios/seabios.bin index 1f4ecc0c..5c17cbd3 100644 Binary files a/bios/seabios.bin and b/bios/seabios.bin differ diff --git a/bios/seabios.config b/bios/seabios.config new file mode 100644 index 00000000..2be1f894 --- /dev/null +++ b/bios/seabios.config @@ -0,0 +1,114 @@ +# +# Automatically generated file; DO NOT EDIT. +# SeaBIOS Configuration +# + +# +# General Features +# +# CONFIG_COREBOOT is not set +CONFIG_QEMU=y +# CONFIG_CSM is not set +CONFIG_QEMU_HARDWARE=y +CONFIG_XEN=y +CONFIG_THREADS=y +# CONFIG_RELOCATE_INIT is not set +# CONFIG_BOOTMENU is not set +CONFIG_BOOTORDER=y +CONFIG_MULTIBOOT=y +CONFIG_ENTRY_EXTRASTACK=y +CONFIG_MALLOC_UPPERMEMORY=y +CONFIG_ROM_SIZE=0 + +# +# Hardware support +# +CONFIG_ATA=y +CONFIG_ATA_DMA=y +CONFIG_ATA_PIO32=y +CONFIG_AHCI=y +CONFIG_SDCARD=y +CONFIG_VIRTIO_BLK=y +CONFIG_VIRTIO_SCSI=y +CONFIG_PVSCSI=y +CONFIG_ESP_SCSI=y +CONFIG_LSI_SCSI=y +CONFIG_MEGASAS=y +CONFIG_MPT_SCSI=y +CONFIG_FLOPPY=y +CONFIG_FLASH_FLOPPY=y +# CONFIG_NVME is not set +CONFIG_PS2PORT=y +# CONFIG_USB is not set +CONFIG_SERIAL=y +# CONFIG_SERCON is not set +CONFIG_LPT=y +CONFIG_RTC_TIMER=y +CONFIG_HARDWARE_IRQ=y +CONFIG_USE_SMM=y +CONFIG_CALL32_SMM=y +CONFIG_MTRR_INIT=y +CONFIG_PMTIMER=y +CONFIG_TSC_TIMER=y + +# +# BIOS interfaces +# +CONFIG_DRIVES=y +CONFIG_CDROM_BOOT=y +CONFIG_CDROM_EMU=y +CONFIG_PCIBIOS=y +CONFIG_APMBIOS=y +CONFIG_PNPBIOS=y +CONFIG_OPTIONROMS=y +CONFIG_PMM=y +CONFIG_BOOT=y +CONFIG_KEYBOARD=y +CONFIG_KBD_CALL_INT15_4F=y +CONFIG_MOUSE=y +CONFIG_S3_RESUME=y +CONFIG_VGAHOOKS=y +# CONFIG_DISABLE_A20 is not set +# CONFIG_WRITABLE_UPPERMEMORY is not set +CONFIG_TCGBIOS=y + +# +# BIOS Tables +# +CONFIG_PIRTABLE=y +CONFIG_MPTABLE=y +# CONFIG_SMBIOS is not set +CONFIG_ACPI=y +CONFIG_ACPI_DSDT=y +CONFIG_FW_ROMFILE_LOAD=y + +# +# VGA ROM +# +# CONFIG_NO_VGABIOS is not set +# CONFIG_VGA_STANDARD_VGA is not set +# CONFIG_VGA_CIRRUS is not set +CONFIG_VGA_BOCHS=y +# CONFIG_VGA_GEODEGX2 is not set +# CONFIG_VGA_GEODELX is not set +# CONFIG_DISPLAY_BOCHS is not set +# CONFIG_VGA_RAMFB is not set +CONFIG_VGA_BOCHS_STDVGA=y +# CONFIG_VGA_BOCHS_VMWARE is not set +# CONFIG_VGA_BOCHS_QXL is not set +# CONFIG_VGA_BOCHS_VIRTIO is not set +CONFIG_BUILD_VGABIOS=y +CONFIG_VGA_STDVGA_PORTS=y +CONFIG_VGA_FIXUP_ASM=y +CONFIG_VGA_ALLOCATE_EXTRA_STACK=y +CONFIG_VGA_EXTRA_STACK_SIZE=512 +CONFIG_VGA_VBE=y +CONFIG_VGA_PCI=y +CONFIG_OVERRIDE_PCI_ID=y +CONFIG_VGA_VID=0x1234 +CONFIG_VGA_DID=0x1111 + +# +# Debugging +# +CONFIG_DEBUG_LEVEL=0 diff --git a/bios/vgabios-debug.bin b/bios/vgabios-debug.bin index 7ef7eb82..73ec94fd 100644 Binary files a/bios/vgabios-debug.bin and b/bios/vgabios-debug.bin differ diff --git a/bios/vgabios.bin b/bios/vgabios.bin index b5f925e1..e1b6db46 100644 Binary files a/bios/vgabios.bin and b/bios/vgabios.bin differ diff --git a/debug.html b/debug.html index 6d0a5241..e347b7a8 100644 --- a/debug.html +++ b/debug.html @@ -1,7 +1,7 @@ -Virtual x86 +Virtual x86 (debug) @@ -11,22 +11,63 @@

Debugger

- + + +
+ + + + + + +
+ + + + - + +
+ + + + +
+ + + + + + + +
+ + +
+ + + + + +
+ + + + + + + + +
+ - - - - - - - + +
- Floppy disk image +
- Master Hard drive disk image +
@@ -67,41 +102,59 @@ - Multiboot kernel image +
-
+ Disk images are not uploaded to the server
- Memory size + MB
- Video Memory size + MB
+ + + + + + +
- - Boot order + + +
+ + + + +
+ + + + - - - - @@ -155,7 +194,7 @@ - + @@ -180,10 +219,7 @@

-    

-
     
-
     
@@ -196,10 +232,11 @@ +