├── .editorconfig ├── .github └── workflows │ └── release.yml ├── .gitignore ├── .travis-run-integration-acpi.sh ├── .travis-run-integration.sh ├── .travis-run-nasm.sh ├── .travis-run-unit-qemu.sh ├── .travis-run-unit.sh ├── .travis.yml ├── LICENSE ├── Makefile ├── Readme.md ├── bios ├── .gitignore ├── COPYING.LESSER ├── bochs-bios.bin ├── bochs-vgabios.bin ├── seabios-debug.bin ├── seabios.bin ├── vgabios-debug.bin └── vgabios.bin ├── build ├── libv86.js ├── libv86.js.map ├── v86_all.js └── v86_all.js.map ├── debug.html ├── docs ├── .gitignore ├── api.md ├── archlinux.md ├── build.js ├── events.md ├── filesystem.md ├── linux-9p-image.md ├── networking.md └── template.md.ejs ├── examples ├── arch.html ├── async_load.html ├── basic.html ├── destroy.html ├── lang.html ├── lang2.html ├── lua.html ├── nodejs.js ├── nodejs_state.js ├── save_restore.html ├── serial.html ├── two_instances.html ├── worker.html └── worker.js ├── favicon.png ├── index.html ├── lib ├── 9p.js ├── closure-base.js ├── esprima-min.js ├── esprima.js ├── filesystem.js ├── jor1k.js ├── marshall.js ├── utf8.js ├── walk-min.js └── walk.js ├── loader.js ├── package.json ├── src ├── acpi.js ├── adapter-externs.js ├── apic.js ├── arith.js ├── browser │ ├── dummy_screen.js │ ├── keyboard.js │ ├── lib.js │ ├── main.js │ ├── modem.js │ ├── mouse.js │ ├── network.js │ ├── screen.js │ ├── serial.js │ ├── speaker.js │ ├── starter.js │ └── worker_bus.js ├── bus.js ├── config.js ├── const.js ├── cpu.js ├── debug.js ├── dma.js ├── elf.js ├── externs.js ├── floppy.js ├── fpu.js ├── hpet.js ├── ide.js ├── instructions.js ├── io.js ├── ioapic.js ├── lib.js ├── log.js ├── main.js ├── memory.js ├── misc_instr.js ├── modrm.js ├── ne2k.js ├── pci.js ├── pic.js ├── pit.js ├── ps2.js ├── rtc.js ├── sb16.js ├── state.js ├── string.js ├── translate.js ├── uart.js ├── vga.js └── virtio.js ├── tests ├── Readme.md ├── full │ └── run.js ├── kvm-unit-tests │ ├── .gitignore │ ├── COPYRIGHT │ ├── MAINTAINERS │ ├── Makefile │ ├── README.md │ ├── configure │ ├── lib │ │ ├── abort.c │ │ ├── alloc.c │ │ ├── alloc.h │ │ ├── argv.c │ │ ├── asm-generic │ │ │ ├── atomic.h │ │ │ ├── barrier.h │ │ │ ├── io.h │ │ │ ├── page.h │ │ │ ├── pci-host-bridge.h │ │ │ ├── pci.h │ │ │ └── spinlock.h │ │ ├── auxinfo.c │ │ ├── auxinfo.h │ │ ├── bitops.h │ │ ├── chr-testdev.c │ │ ├── chr-testdev.h │ │ ├── devicetree.c │ │ ├── devicetree.h │ │ ├── errata.h │ │ ├── kbuild.h │ │ ├── libcflat.h │ │ ├── libfdt │ │ │ ├── Makefile.libfdt │ │ │ ├── README │ │ │ ├── fdt.c │ │ │ ├── fdt.h │ │ │ ├── fdt_empty_tree.c │ │ │ ├── fdt_ro.c │ │ │ ├── fdt_rw.c │ │ │ ├── fdt_strerror.c │ │ │ ├── fdt_sw.c │ │ │ ├── fdt_wip.c │ │ │ ├── libfdt.h │ │ │ ├── libfdt_env.h │ │ │ ├── libfdt_internal.h │ │ │ └── version.lds │ │ ├── linux │ │ │ ├── const.h │ │ │ ├── pci_regs.h │ │ │ └── psci.h │ │ ├── pci-edu.c │ │ ├── pci-edu.h │ │ ├── pci-host-generic.c │ │ ├── pci-host-generic.h │ │ ├── pci-testdev.c │ │ ├── pci.c │ │ ├── pci.h │ │ ├── printf.c │ │ ├── report.c │ │ ├── setjmp.h │ │ ├── stack.c │ │ ├── stack.h │ │ ├── string.c │ │ ├── string.h │ │ ├── util.c │ │ ├── util.h │ │ ├── virtio-mmio.c │ │ ├── virtio-mmio.h │ │ ├── virtio.c │ │ ├── virtio.h │ │ └── x86 │ │ │ ├── acpi.c │ │ │ ├── acpi.h │ │ │ ├── apic-defs.h │ │ │ ├── apic.c │ │ │ ├── apic.h │ │ │ ├── asm │ │ │ ├── barrier.h │ │ │ ├── bitops.h │ │ │ ├── io.h │ │ │ ├── page.h │ │ │ ├── pci.h │ │ │ ├── spinlock.h │ │ │ └── stack.h │ │ │ ├── atomic.c │ │ │ ├── atomic.h │ │ │ ├── desc.c │ │ │ ├── desc.h │ │ │ ├── fake-apic.h │ │ │ ├── fwcfg.c │ │ │ ├── fwcfg.h │ │ │ ├── intel-iommu.c │ │ │ ├── intel-iommu.h │ │ │ ├── io.c │ │ │ ├── isr.c │ │ │ ├── isr.h │ │ │ ├── msr.h │ │ │ ├── processor.h │ │ │ ├── setjmp32.S │ │ │ ├── setjmp64.S │ │ │ ├── setup.c │ │ │ ├── smp.c │ │ │ ├── smp.h │ │ │ ├── stack.c │ │ │ ├── vm.c │ │ │ └── vm.h │ ├── run.js │ └── x86 │ │ ├── Makefile │ │ ├── Makefile.common │ │ ├── Makefile.i386 │ │ ├── Makefile.x86_64 │ │ ├── README │ │ ├── access.c │ │ ├── apic.c │ │ ├── asyncpf.c │ │ ├── cmpxchg8b.c │ │ ├── cstart.S │ │ ├── cstart64.S │ │ ├── debug.c │ │ ├── emulator.c │ │ ├── eventinj.c │ │ ├── flat.lds │ │ ├── hypercall.c │ │ ├── hyperv.c │ │ ├── hyperv.h │ │ ├── hyperv_clock.c │ │ ├── hyperv_stimer.c │ │ ├── hyperv_synic.c │ │ ├── idt_test.c │ │ ├── init.c │ │ ├── intel-iommu.c │ │ ├── ioapic.c │ │ ├── ioram.h │ │ ├── kvmclock.c │ │ ├── kvmclock.h │ │ ├── kvmclock_test.c │ │ ├── memory.c │ │ ├── msr.c │ │ ├── pcid.c │ │ ├── pku.c │ │ ├── pmu.c │ │ ├── port80.c │ │ ├── realmode.c │ │ ├── realmode.lds │ │ ├── rmap_chain.c │ │ ├── run │ │ ├── s3.c │ │ ├── setjmp.c │ │ ├── sieve.c │ │ ├── smap.c │ │ ├── smptest.c │ │ ├── svm.c │ │ ├── svm.h │ │ ├── taskswitch.c │ │ ├── taskswitch2.c │ │ ├── tsc.c │ │ ├── tsc_adjust.c │ │ ├── tscdeadline_latency.c │ │ ├── types.h │ │ ├── unittests.cfg │ │ ├── vmexit.c │ │ ├── vmx.c │ │ ├── vmx.h │ │ ├── vmx_tests.c │ │ └── xsave.c ├── nasm │ ├── Makefile │ ├── Readme.md │ ├── comiss.asm │ ├── cvtpi2ps.asm │ ├── cvtps2pi.asm │ ├── cvttps2pi.asm │ ├── emms.asm │ ├── footer.inc │ ├── gdbauto │ ├── header.inc │ ├── movaps.asm │ ├── movd.asm │ ├── movntpd.asm │ ├── movntps.asm │ ├── movq.asm │ ├── packssdw.asm │ ├── packsswb.asm │ ├── packuswb.asm │ ├── paddb.asm │ ├── paddd.asm │ ├── paddsb.asm │ ├── paddsw.asm │ ├── paddusb.asm │ ├── paddusw.asm │ ├── paddw.asm │ ├── pand.asm │ ├── pandn.asm │ ├── pcmpeqb.asm │ ├── pcmpeqd.asm │ ├── pcmpeqw.asm │ ├── pcmpgtb.asm │ ├── pcmpgtd.asm │ ├── pcmpgtw.asm │ ├── pmaddwd.asm │ ├── pmulhw.asm │ ├── pmullw.asm │ ├── pmuludq.asm │ ├── por.asm │ ├── pshufw.asm │ ├── pslld.asm │ ├── psllq.asm │ ├── psllw.asm │ ├── psrad.asm │ ├── psraw.asm │ ├── psrld.asm │ ├── psrlq.asm │ ├── psrlw.asm │ ├── psubb.asm │ ├── psubd.asm │ ├── psubsb.asm │ ├── psubsw.asm │ ├── psubusb.asm │ ├── psubusw.asm │ ├── psubw.asm │ ├── punpckhbw.asm │ ├── punpckhdq.asm │ ├── punpckhwd.asm │ ├── punpcklbw.asm │ ├── punpckldq.asm │ ├── punpcklwd.asm │ ├── pxor.asm │ ├── run.js │ └── ucomiss.asm ├── perf-irhydra │ ├── clean.sh │ └── run.sh └── qemu │ ├── LICENSE │ ├── Makefile │ ├── Readme.md │ ├── compiler.h │ ├── config-host.h │ ├── run.js │ ├── test-i386-code16.S │ ├── test-i386-muldiv.h │ ├── test-i386-shift.h │ ├── test-i386-vm86.S │ ├── test-i386.c │ └── test-i386.h └── v86.css /.editorconfig: -------------------------------------------------------------------------------- 1 | root=true 2 | 3 | [*.js] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 4 7 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | 6 | jobs: 7 | release: 8 | name: Release to GitHub 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - name: Checkout repository 13 | uses: actions/checkout@v2 14 | 15 | - name: Build v86 16 | run: make build/libv86.js 17 | 18 | - name: Release to GitHub 19 | uses: marvinpinto/action-automatic-releases@latest 20 | with: 21 | title: Latest Release 22 | automatic_release_tag: latest 23 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 24 | files: | 25 | build/*.js 26 | build/*.js.map 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.swo 3 | tests/qemu/test-i386 4 | tests/jit-paging/test-jit 5 | closure-compiler/ 6 | images/ 7 | *.bak 8 | *.orig 9 | *.o 10 | *.img 11 | *.fixture 12 | *.fuse_hidden* 13 | *.DS_Store 14 | node_modules/ 15 | -------------------------------------------------------------------------------- /.travis-run-integration-acpi.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | mkdir -p images 4 | (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}) 5 | make build/libv86.js useacpi=true 6 | tests/full/run.js 7 | -------------------------------------------------------------------------------- /.travis-run-integration.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | mkdir -p images 4 | (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}) 5 | make build/libv86.js 6 | tests/full/run.js 7 | -------------------------------------------------------------------------------- /.travis-run-nasm.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | make nasmtests 4 | -------------------------------------------------------------------------------- /.travis-run-unit-qemu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | mkdir -p images 4 | (cd images && curl --compressed -O https://copy.sh/v86/images/linux3.iso) 5 | make qemutests 6 | -------------------------------------------------------------------------------- /.travis-run-unit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | make build/libv86.js 4 | (cd tests/kvm-unit-tests && ./configure && make) 5 | tests/kvm-unit-tests/run.js tests/kvm-unit-tests/x86/realmode.flat 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "6.10.2" 4 | dist: trusty 5 | before_install: 6 | - sudo dpkg --add-architecture i386 7 | - sudo apt-get update -qq 8 | install: 9 | - sudo apt-get install -y gcc-multilib nasm gdb 10 | script: 11 | - "./.travis-run-$TEST_SUITE.sh" 12 | env: 13 | - TEST_SUITE=unit 14 | - TEST_SUITE=integration 15 | - TEST_SUITE=integration-acpi 16 | - TEST_SUITE=unit-qemu 17 | - TEST_SUITE=nasm 18 | matrix: 19 | allow_failures: 20 | - env: TEST_SUITE=unit-qemu 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2018, Fabian Hemmer 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 | 24 | The views and conclusions contained in the software and documentation are those 25 | of the authors and should not be interpreted as representing official policies, 26 | either expressed or implied, of the FreeBSD Project. 27 | -------------------------------------------------------------------------------- /bios/.gitignore: -------------------------------------------------------------------------------- 1 | *.gz 2 | -------------------------------------------------------------------------------- /bios/bochs-bios.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelsuft/v86-wasmless/3f7360b301732983de0aef027d7b5abda7ce3b0d/bios/bochs-bios.bin -------------------------------------------------------------------------------- /bios/bochs-vgabios.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelsuft/v86-wasmless/3f7360b301732983de0aef027d7b5abda7ce3b0d/bios/bochs-vgabios.bin -------------------------------------------------------------------------------- /bios/seabios-debug.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelsuft/v86-wasmless/3f7360b301732983de0aef027d7b5abda7ce3b0d/bios/seabios-debug.bin -------------------------------------------------------------------------------- /bios/seabios.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelsuft/v86-wasmless/3f7360b301732983de0aef027d7b5abda7ce3b0d/bios/seabios.bin -------------------------------------------------------------------------------- /bios/vgabios-debug.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelsuft/v86-wasmless/3f7360b301732983de0aef027d7b5abda7ce3b0d/bios/vgabios-debug.bin -------------------------------------------------------------------------------- /bios/vgabios.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelsuft/v86-wasmless/3f7360b301732983de0aef027d7b5abda7ce3b0d/bios/vgabios.bin -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /docs/build.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var markdox = require("markdox"); 4 | 5 | var options = { 6 | output: __dirname + "/api.md", 7 | template: __dirname + "/template.md.ejs" 8 | }; 9 | 10 | var files = [ 11 | __dirname + "/../src/browser/starter.js", 12 | ]; 13 | 14 | markdox.process(files, options, function() { 15 | console.log("Ok. %s written.", options.output); 16 | }); 17 | -------------------------------------------------------------------------------- /docs/events.md: -------------------------------------------------------------------------------- 1 | Here is a list of events that can be listened to using 2 | [`add_listener`](api.md#add_listenerstring-event-function-listener). These 3 | can be used to programmatically control the emulator. Events cannot be sent to 4 | the emulator (although it is internally implemented that way), use the 5 | [API](api.md) methods for that. 6 | 7 | ### Serial terminal 8 | 9 | See also: [serial.js](../src/browser/serial.js). 10 | 11 | - `serial0-output-char` - `string chr` 12 | 13 | ### Network 14 | 15 | See also: [network.js](../src/browser/network.js). 16 | 17 | - `net0-receive` - `Uint8Array buffer` 18 | 19 | ### Screen 20 | 21 | See also: [screen.js](../src/browser/screen.js). 22 | 23 | - `screen-set-mode` - `boolean is_graphic` 24 | - `screen-put-char` - `[number row, number col, number chr, number bg_color, number fg_color]` 25 | - `screen-put-pixel-linear` - `[number addr, number value]` 26 | - `screen-put-pixel-linear32` - `[number addr, number value]` 27 | - `screen-set-size-text` - `[number cols_count, number rows_count]` 28 | - `screen-set-size-graphical` - `[number width, number height, number virtual_width, number virtual_height, number bpp]` 29 | - `screen-update-cursor` - `[number row, number col]` 30 | - `screen-update-cursor-scanline` - `[number cursor_scanline_start, number cursor_scanline_end]` 31 | 32 | 33 | -------------------------------------------------------------------------------- /docs/filesystem.md: -------------------------------------------------------------------------------- 1 | A 9p filesystem is supported by the emulator, using a virtio transport. Using 2 | it, files can be exchanged with the guest OS, see 3 | [`create_file`](api.md#create_filestring-file-uint8array-data-functionobject-callback) 4 | [`create_file`](api.md#create_filestring-file-uint8array-data-functionobject-callback) 5 | and 6 | [`read_file`](api.md#read_filestring-file-functionobject-uint8array-callback). It can 7 | be enabled by passing the following options to `V86Starter`: 8 | 9 | ```javascript 10 | filesystem: { 11 | basefs: "../9p/fs.json", 12 | baseurl: "../9p/base/", 13 | } 14 | ``` 15 | 16 | Here, `basefs` is a json file created using 17 | [fs2json](https://github.com/copy/fs2json). The base url is the prefix of a url 18 | from which the files are available. For instance, if the 9p filesystem has a 19 | file `/bin/sh`, that file must be accessible from 20 | `http://localhost/9p/base/bin/sh`. If `basefs` and `baseurl` are omitted, an 21 | empty 9p filesystem is created. 22 | 23 | The `mount_tag` of the 9p device is `host9p`. In order to mount it in the 24 | guest, use: 25 | 26 | ```sh 27 | mount -t 9p host9p /mnt/9p/ 28 | ``` 29 | -------------------------------------------------------------------------------- /docs/linux-9p-image.md: -------------------------------------------------------------------------------- 1 | In order to create a Linux image that can mount the 9p file system, use add the following lines to the kernel config: 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/networking.md: -------------------------------------------------------------------------------- 1 | Emulating a network card is supported. It can be used by passing the 2 | `network_relay_url` option to `V86Starter`. The url must point to a running 3 | WebSockets Proxy. The source code for WebSockets Proxy can be found at 4 | https://github.com/benjamincburns/websockproxy. 5 | 6 | The network card could also be controlled programatically, but this is 7 | currently not exposed. 8 | -------------------------------------------------------------------------------- /docs/template.md.ejs: -------------------------------------------------------------------------------- 1 | .]/g, ""); 8 | str = str.replace(/[^a-z0-9_-]+/gi, "-"); 9 | str = str.toLowerCase(); 10 | 11 | return str; 12 | } 13 | 14 | docfiles.forEach(function(doc) 15 | { 16 | doc.javadoc.forEach(function(comment) 17 | { 18 | var tags = comment.raw.tags; 19 | 20 | comment.tagsByType = comment.raw.tags.reduce(function(result, tag) 21 | { 22 | result[tag.type] = tag; 23 | return result; 24 | }, {}); 25 | 26 | comment.ignore = "ignore" in comment.tagsByType; 27 | 28 | if(comment.name && !comment.ignore) 29 | { 30 | if(comment.isMethod || comment.isFunction) 31 | { 32 | var args = comment.paramTags.map(function(c) 33 | { 34 | return c.joinedTypes + " " + c.name; 35 | }).join(", "); 36 | 37 | var returnVal = ""; 38 | 39 | if(comment.returnTags[0]) 40 | { 41 | returnVal = " -> " + comment.returnTags[0].joinedTypes; 42 | } 43 | comment.args = args; 44 | comment.returnVal = returnVal; 45 | comment.longName = comment.name + "(" + comment.args + ")" + comment.returnVal; 46 | 47 | ?># \n" ?> 106 | 107 | 108 | -------------------------------------------------------------------------------- /examples/arch.html: -------------------------------------------------------------------------------- 1 | 2 | Archlinux 3 | 4 | 5 | 73 | 74 | 75 | Restore from file: 76 |
77 | 78 | 79 |
80 |
81 | 82 |
83 | -------------------------------------------------------------------------------- /examples/async_load.html: -------------------------------------------------------------------------------- 1 | 2 | Asynchronous loading of disk images 3 | 4 | 5 | 38 | 39 |
40 |
41 | 42 |
43 | -------------------------------------------------------------------------------- /examples/basic.html: -------------------------------------------------------------------------------- 1 | 2 | Basic Emulator 3 | 4 | 5 | 27 | 28 | 29 |
30 |
31 | 32 |
33 | -------------------------------------------------------------------------------- /examples/destroy.html: -------------------------------------------------------------------------------- 1 | 2 | Destroyable Emulator 3 | 4 | 5 | 29 | 30 |
31 |
32 | 33 |
34 | -------------------------------------------------------------------------------- /examples/lang.html: -------------------------------------------------------------------------------- 1 | 2 | Basic Emulator 3 | 4 | 5 | 79 | 80 |
 
81 | 82 | 83 |
84 |
85 | 86 |
87 | 88 |
89 | 90 |

91 | 


--------------------------------------------------------------------------------
/examples/lang2.html:
--------------------------------------------------------------------------------
  1 | 
  2 | Interpreter 2
  3 | 
  4 | 
  5 | 
 90 | 
 91 | 
0s -- 
92 |
93 | 94 |
 95 | 
 96 | 
97 |
98 | 99 | 100 |
101 |
102 | 103 |
104 | 105 | -------------------------------------------------------------------------------- /examples/nodejs.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | var fs = require("fs"); 5 | var V86Starter = require("../build/libv86.js").V86Starter; 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/linux.iso"); 14 | 15 | process.stdin.setRawMode(true); 16 | process.stdin.resume(); 17 | process.stdin.setEncoding("utf8"); 18 | 19 | var boot_start = Date.now(); 20 | var booted = false; 21 | 22 | console.log("Now booting, please stand by ..."); 23 | 24 | var emulator = new V86Starter({ 25 | bios: { buffer: bios }, 26 | cdrom: { buffer: linux }, 27 | autostart: true, 28 | }); 29 | 30 | emulator.add_listener("serial0-output-char", function(chr) 31 | { 32 | if(!booted) 33 | { 34 | var now = Date.now(); 35 | console.log("Took %dms to boot", now - boot_start); 36 | booted = true; 37 | } 38 | 39 | process.stdout.write(chr); 40 | }); 41 | 42 | process.stdin.on("data", function(c) 43 | { 44 | if(c === "\u0003") 45 | { 46 | // ctrl c 47 | emulator.stop(); 48 | process.stdin.pause(); 49 | } 50 | else 51 | { 52 | emulator.serial0_send(c); 53 | } 54 | }); 55 | -------------------------------------------------------------------------------- /examples/nodejs_state.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | var fs = require("fs"); 5 | var V86Starter = require("../build/libv86.js").V86Starter; 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/linux.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 V86Starter({ 24 | bios: { buffer: bios }, 25 | cdrom: { buffer: linux }, 26 | autostart: true, 27 | }); 28 | 29 | emulator.add_listener("serial0-output-char", function(chr) 30 | { 31 | process.stdout.write(chr); 32 | }); 33 | 34 | var state; 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 if(c === "\x1b\x4f\x51") 45 | { 46 | // f2 47 | emulator.save_state(function(err, s) 48 | { 49 | console.log("--- Saved ---"); 50 | if(err) 51 | { 52 | throw err; 53 | } 54 | 55 | state = s; 56 | }); 57 | } 58 | else if(c === "\x1b\x4f\x52") 59 | { 60 | // f3 61 | if(state) 62 | { 63 | console.log("--- Restored ---"); 64 | emulator.restore_state(state); 65 | } 66 | } 67 | else 68 | { 69 | emulator.serial0_send(c); 70 | } 71 | }); 72 | -------------------------------------------------------------------------------- /examples/save_restore.html: -------------------------------------------------------------------------------- 1 | 2 | Save and restore 3 | 4 | 5 | 98 | 99 | 100 | 101 | Restore from file: 102 |
103 | 104 | 105 |
106 |
107 | 108 |
109 | -------------------------------------------------------------------------------- /examples/serial.html: -------------------------------------------------------------------------------- 1 | 2 | Serial example 3 | 4 | 5 | 76 | 77 | 79 | 80 | 81 | 82 |
83 |
84 | 85 |
86 | -------------------------------------------------------------------------------- /examples/two_instances.html: -------------------------------------------------------------------------------- 1 | 2 | Two emulators 3 | 4 | 5 | 67 | 68 | Click on a screen to control it.
69 | 70 |
71 |
72 | 73 |
74 | 75 |
76 |
77 | 78 |
79 | -------------------------------------------------------------------------------- /examples/worker.html: -------------------------------------------------------------------------------- 1 | 2 | Worker 3 | 4 | 30 | 31 | s 32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /examples/worker.js: -------------------------------------------------------------------------------- 1 | importScripts("../build/libv86.js"); 2 | 3 | var emulator = new V86Starter({ 4 | memory_size: 32 * 1024 * 1024, 5 | vga_memory_size: 2 * 1024 * 1024, 6 | bios: { 7 | url: "../bios/seabios.bin", 8 | }, 9 | vga_bios: { 10 | url: "../bios/vgabios.bin", 11 | }, 12 | cdrom: { 13 | url: "../images/linux.iso", 14 | }, 15 | autostart: true, 16 | }); 17 | 18 | 19 | emulator.add_listener("serial0-output-char", function(chr) 20 | { 21 | this.postMessage(chr); 22 | }.bind(this)); 23 | 24 | this.onmessage = function(e) 25 | { 26 | emulator.serial0_send(e.data); 27 | }; 28 | 29 | -------------------------------------------------------------------------------- /favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelsuft/v86-wasmless/3f7360b301732983de0aef027d7b5abda7ce3b0d/favicon.png -------------------------------------------------------------------------------- /lib/jor1k.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // jor1k compatibility 4 | 5 | var VIRTIO_MAGIC_REG = 0x0; 6 | var VIRTIO_VERSION_REG = 0x4; 7 | var VIRTIO_DEVICE_REG = 0x8; 8 | var VIRTIO_VENDOR_REG = 0xc; 9 | var VIRTIO_HOSTFEATURES_REG = 0x10; 10 | var VIRTIO_HOSTFEATURESSEL_REG = 0x14; 11 | var VIRTIO_GUESTFEATURES_REG = 0x20; 12 | var VIRTIO_GUESTFEATURESSEL_REG = 0x24; 13 | var VIRTIO_GUEST_PAGE_SIZE_REG = 0x28; 14 | var VIRTIO_QUEUESEL_REG = 0x30; 15 | var VIRTIO_QUEUENUMMAX_REG = 0x34; 16 | var VIRTIO_QUEUENUM_REG = 0x38; 17 | var VIRTIO_QUEUEALIGN_REG = 0x3C; 18 | var VIRTIO_QUEUEPFN_REG = 0x40; 19 | var VIRTIO_QUEUENOTIFY_REG = 0x50; 20 | var VIRTIO_INTERRUPTSTATUS_REG = 0x60; 21 | var VIRTIO_INTERRUPTACK_REG = 0x64; 22 | var VIRTIO_STATUS_REG = 0x70; 23 | 24 | /** @const */ 25 | var VRING_DESC_F_NEXT = 1; /* This marks a buffer as continuing via the next field. */ 26 | /** @const */ 27 | var VRING_DESC_F_WRITE = 2; /* This marks a buffer as write-only (otherwise read-only). */ 28 | /** @const */ 29 | var VRING_DESC_F_INDIRECT = 4; /* This means the buffer contains a list of buffer descriptors. */ 30 | 31 | 32 | function hex8(n) 33 | { 34 | return h(n); 35 | } 36 | 37 | var message = {}; 38 | 39 | /** @param {...string} log */ 40 | message.Debug = function(log) 41 | { 42 | dbg_log([].slice.apply(arguments).join(" "), LOG_9P); 43 | } 44 | 45 | message.Abort = function() 46 | { 47 | if(DEBUG) 48 | { 49 | throw "abort"; 50 | } 51 | } 52 | 53 | 54 | // XXX: Should go through emulator interface 55 | var LoadBinaryResource; 56 | 57 | if(typeof XMLHttpRequest !== "undefined") 58 | { 59 | LoadBinaryResource = function(url, OnSuccess, OnError) { 60 | var req = new XMLHttpRequest(); 61 | req.open('GET', url, true); 62 | req.responseType = "arraybuffer"; 63 | req.onreadystatechange = function () { 64 | if (req.readyState != 4) { 65 | return; 66 | } 67 | if ((req.status != 200) && (req.status != 0)) { 68 | OnError("Error: Could not load file " + url); 69 | return; 70 | } 71 | var arrayBuffer = req.response; 72 | if (arrayBuffer) { 73 | OnSuccess(arrayBuffer); 74 | } else { 75 | OnError("Error: No data received from: " + url); 76 | } 77 | }; 78 | /* 79 | req.onload = function(e) 80 | { 81 | var arrayBuffer = req.response; 82 | if (arrayBuffer) { 83 | OnLoadFunction(arrayBuffer); 84 | } 85 | }; 86 | */ 87 | req.send(null); 88 | } 89 | } 90 | else 91 | { 92 | LoadBinaryResource = function(url, OnSuccess, OnError) 93 | { 94 | //console.log(url); 95 | require("fs")["readFile"](url, function(err, data) 96 | { 97 | if(err) 98 | { 99 | OnError(err); 100 | } 101 | else 102 | { 103 | OnSuccess(new Uint8Array(data).buffer); 104 | } 105 | }); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /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= 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 | -------------------------------------------------------------------------------- /src/bus.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var Bus = {}; 4 | 5 | /** @constructor */ 6 | function BusConnector() 7 | { 8 | this.listeners = {}; 9 | this.pair = undefined; 10 | } 11 | 12 | /** 13 | * @param {string} name 14 | * @param {function(?)} fn 15 | * @param {Object} this_value 16 | */ 17 | BusConnector.prototype.register = function(name, fn, this_value) 18 | { 19 | var listeners = this.listeners[name]; 20 | 21 | if(listeners === undefined) 22 | { 23 | listeners = this.listeners[name] = []; 24 | } 25 | 26 | listeners.push({ 27 | fn: fn, 28 | this_value: this_value, 29 | }); 30 | }; 31 | 32 | /** 33 | * Unregister one message with the given name and callback 34 | * 35 | * @param {string} name 36 | * @param {function()} fn 37 | */ 38 | BusConnector.prototype.unregister = function(name, fn) 39 | { 40 | var listeners = this.listeners[name]; 41 | 42 | if(listeners === undefined) 43 | { 44 | return; 45 | } 46 | 47 | this.listeners[name] = listeners.filter(function(l) 48 | { 49 | return l.fn !== fn; 50 | }); 51 | }; 52 | 53 | /** 54 | * Send ("emit") a message 55 | * 56 | * @param {string} name 57 | * @param {*=} value 58 | * @param {*=} unused_transfer 59 | */ 60 | BusConnector.prototype.send = function(name, value, unused_transfer) 61 | { 62 | if(!this.pair) 63 | { 64 | return; 65 | } 66 | 67 | var listeners = this.pair.listeners[name]; 68 | 69 | if(listeners === undefined) 70 | { 71 | return; 72 | } 73 | 74 | for(var i = 0; i < listeners.length; i++) 75 | { 76 | var listener = listeners[i]; 77 | listener.fn.call(listener.this_value, value); 78 | } 79 | }; 80 | 81 | /** 82 | * Send a message, guaranteeing that it is received asynchronously 83 | * 84 | * @param {string} name 85 | * @param {Object=} value 86 | */ 87 | BusConnector.prototype.send_async = function(name, value) 88 | { 89 | dbg_assert(arguments.length === 1 || arguments.length === 2); 90 | 91 | setTimeout(this.send.bind(this, name, value), 0); 92 | }; 93 | 94 | Bus.create = function() 95 | { 96 | var c0 = new BusConnector(); 97 | var c1 = new BusConnector(); 98 | 99 | c0.pair = c1; 100 | c1.pair = c0; 101 | 102 | return [c0, c1]; 103 | }; 104 | 105 | -------------------------------------------------------------------------------- /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 = false; 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 | * Enables logging of page faults, quite verbose 24 | */ 25 | var LOG_PAGE_FAULTS = false; 26 | 27 | 28 | var LOG_LEVEL = LOG_ALL & ~LOG_PS2 & ~LOG_PIT & ~LOG_VIRTIO & ~LOG_9P & ~LOG_PIC & 29 | ~LOG_DMA & ~LOG_SERIAL & ~LOG_NET & ~LOG_FLOPPY & ~LOG_DISK; 30 | 31 | /** 32 | * @const 33 | * Draws entire buffer and visualizes the layers that would be drawn 34 | */ 35 | var DEBUG_SCREEN_LAYERS = DEBUG && false; 36 | 37 | 38 | /** @const */ 39 | var ENABLE_HPET = DEBUG && false; 40 | 41 | /** 42 | * @define {boolean} 43 | * Overridden by closure compiler 44 | */ 45 | var ENABLE_ACPI = false; 46 | 47 | /** @const */ 48 | var WINNT_FIX = false; 49 | 50 | /** 51 | * @const 52 | * How many cycles the CPU does at a time before running hardware timers 53 | */ 54 | var LOOP_COUNTER = 11001; 55 | 56 | /** 57 | * @const 58 | * How often, in milliseconds, to yield to the browser for rendering and 59 | * running events 60 | */ 61 | var TIME_PER_FRAME = 1; 62 | 63 | /** 64 | * @const 65 | * How many ticks the TSC does per millisecond 66 | */ 67 | var TSC_RATE = 8 * 1024; 68 | 69 | 70 | /** @const */ 71 | var APIC_TIMER_FREQ = TSC_RATE; 72 | 73 | 74 | /** @const */ 75 | var VMWARE_HYPERVISOR_PORT = true; 76 | -------------------------------------------------------------------------------- /src/externs.js: -------------------------------------------------------------------------------- 1 | var performance = {}; 2 | 3 | 4 | 5 | var global = {}; 6 | var require = function(module) {}; 7 | var process = {}; 8 | var __dirname = ""; 9 | 10 | var esprima = { tokenize: {}, parse: {} }; 11 | var acorn = { walk: { simple: {} } }; 12 | 13 | var exports = {}; 14 | var define = {}; 15 | var module = {}; 16 | 17 | // New Web Audio API 18 | 19 | /** 20 | * @constructor 21 | * @extends {AudioNode} 22 | * @param {Object=} options 23 | */ 24 | var AudioWorkletNode = function(context, name, options) 25 | { 26 | this.port = 27 | { 28 | /** 29 | * @param {Object} data 30 | * @param {Object=} transfer 31 | */ 32 | postMessage: function(data, transfer) {} 33 | }; 34 | }; 35 | 36 | /** 37 | * @constructor 38 | */ 39 | var AudioWorkletProcessor = function() 40 | { 41 | this.port = 42 | { 43 | /** 44 | * @param {Object} data 45 | * @param {Object=} transfer 46 | */ 47 | postMessage: function(data, transfer) {} 48 | }; 49 | } 50 | 51 | var AudioWorklet = function() {}; 52 | 53 | AudioContext.prototype.audioWorklet = 54 | { 55 | /** @return {Promise} */ 56 | addModule: function(file) {} 57 | }; 58 | 59 | /** 60 | * @param {string} name 61 | * @param {function()} processor 62 | */ 63 | var registerProcessor = function(name, processor) {} 64 | 65 | /** @const */ 66 | var currentTime = 0; 67 | 68 | /** @const */ 69 | var sampleRate = 0; 70 | -------------------------------------------------------------------------------- /src/log.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var log_data = []; 4 | 5 | function do_the_log(message) 6 | { 7 | if(LOG_TO_FILE) 8 | { 9 | log_data.push(message, "\n"); 10 | } 11 | else 12 | { 13 | console.log(message); 14 | } 15 | } 16 | 17 | /** 18 | * @type {function((string|number), number=)} 19 | * @const 20 | */ 21 | var dbg_log = (function() 22 | { 23 | if(!DEBUG) 24 | { 25 | return function() {}; 26 | } 27 | 28 | /** @const @type {Object.} */ 29 | var dbg_names = LOG_NAMES.reduce(function(a, x) 30 | { 31 | a[x[0]] = x[1]; 32 | return a; 33 | }, {}); 34 | 35 | var log_last_message = ""; 36 | var log_message_repetitions = 0; 37 | 38 | /** 39 | * @param {number=} level 40 | */ 41 | function dbg_log_(stuff, level) 42 | { 43 | if(!DEBUG) return; 44 | 45 | level = level || 1; 46 | 47 | if(level & LOG_LEVEL) 48 | { 49 | var level_name = dbg_names[level] || "", 50 | message = "[" + v86util.pads(level_name, 4) + "] " + stuff; 51 | 52 | if(message === log_last_message) 53 | { 54 | log_message_repetitions++; 55 | 56 | if(log_message_repetitions < 2048) 57 | { 58 | return; 59 | } 60 | } 61 | 62 | var now = new Date(); 63 | var time_str = v86util.pad0(now.getHours(), 2) + ":" + 64 | v86util.pad0(now.getMinutes(), 2) + ":" + 65 | v86util.pad0(now.getSeconds(), 2) + "+" + 66 | v86util.pad0(now.getMilliseconds(), 3) + " "; 67 | 68 | if(log_message_repetitions) 69 | { 70 | if(log_message_repetitions === 1) 71 | { 72 | do_the_log(time_str + log_last_message); 73 | } 74 | else 75 | { 76 | do_the_log("Previous message repeated " + log_message_repetitions + " times"); 77 | } 78 | 79 | log_message_repetitions = 0; 80 | } 81 | 82 | do_the_log(time_str + message); 83 | log_last_message = message; 84 | } 85 | } 86 | 87 | return dbg_log_; 88 | })(); 89 | 90 | /** 91 | * @param {number=} level 92 | */ 93 | function dbg_trace(level) 94 | { 95 | if(!DEBUG) return; 96 | 97 | dbg_log(Error().stack.replace(/(?:(?:t|t16|t32)\.\(anonymous function\)\.)+/g, "t.(anonymous function)."), level); 98 | } 99 | 100 | /** 101 | * console.assert is fucking slow 102 | * @param {string=} msg 103 | * @param {number=} level 104 | */ 105 | function dbg_assert(cond, msg, level) 106 | { 107 | if(!DEBUG) return; 108 | 109 | if(!cond) 110 | { 111 | dbg_assert_failed(msg); 112 | } 113 | }; 114 | 115 | 116 | function dbg_assert_failed(msg) 117 | { 118 | debugger; 119 | console.trace(); 120 | 121 | if(msg) 122 | { 123 | throw "Assert failed: " + msg; 124 | } 125 | else 126 | { 127 | throw "Assert failed"; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/translate.js: -------------------------------------------------------------------------------- 1 | /** @constructor */ 2 | function DynamicTranslator(something) 3 | { 4 | // TODO 5 | dbg_assert(false); 6 | 7 | this.clear_cache = function() {}; 8 | this.cycle_translated = function() {}; 9 | } 10 | -------------------------------------------------------------------------------- /tests/Readme.md: -------------------------------------------------------------------------------- 1 | - [nasm](nasm/): Small unit tests written in assembly, which are run using gdb 2 | on the host. 3 | - [qemu](qemu/): Builds a Linux binary, which tests many CPU features, which 4 | are then compared to a run on the host. 5 | - [kvm-unit-test](kvm-unit-test/): Based on tests from the KVM project, tests 6 | various CPU features. 7 | - [full](full/): Starts several OSes and checks if they boot correctly. 8 | - [perf-irhydra](perf-irhydra/): Manual performance test. Probably not 9 | interesting for you. 10 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyright (C) 2006 Qumranet. 2 | 3 | The files in this directory and its subdirectories are licensed under the 4 | GNU LGPL, version 2. 5 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/MAINTAINERS: -------------------------------------------------------------------------------- 1 | KVM Unit Tests Maintainers 2 | ========================== 3 | 4 | The intention of this file is not to establish who owns what portions of the 5 | code base, but to provide a set of names that developers can consult when they 6 | have a question about a particular subset and also to provide a set of names 7 | to be CC'd when submitting a patch to obtain appropriate review. 8 | 9 | In general, if you have a question about inclusion of a patch, you 10 | should consult the KVM mailing list and not any 11 | specific individual privately. 12 | 13 | Descriptions of section entries: 14 | 15 | M: Mail patches to: FullName 16 | L: Mailing list that is relevant to this area 17 | W: Web-page with status/info 18 | Q: Patchwork web based patch tracking system site 19 | T: SCM tree type and location. Type is one of: git, hg, quilt, stgit. 20 | S: Status, one of the following: 21 | Supported: Someone is actually paid to look after this. 22 | Maintained: Someone actually looks after it. 23 | Odd Fixes: It has a maintainer but they don't have time to do 24 | much other than throw the odd patch in. See below. 25 | Orphan: No current maintainer [but maybe you could take the 26 | role as you write your new code]. 27 | Obsolete: Old code. Something tagged obsolete generally means 28 | it has been replaced by a better system and you 29 | should be using that. 30 | F: Files and directories with wildcard patterns. 31 | A trailing slash includes all files and subdirectory files. 32 | F: drivers/net/ all files in and below drivers/net 33 | F: drivers/net/* all files in drivers/net, but not below 34 | F: */net/* all files in "any top level directory"/net 35 | One pattern per line. Multiple F: lines acceptable. 36 | X: Files and directories that are NOT maintained, same rules as F: 37 | Files exclusions are tested before file matches. 38 | Can be useful for excluding a specific subdirectory, for instance: 39 | F: net/ 40 | X: net/ipv6/ 41 | matches all files in and below net excluding net/ipv6/ 42 | K: Keyword perl extended regex pattern to match content in a 43 | patch or file. For instance: 44 | K: of_get_profile 45 | matches patches or files that contain "of_get_profile" 46 | K: \b(printk|pr_(info|err))\b 47 | matches patches or files that contain one or more of the words 48 | printk, pr_info or pr_err 49 | One regex pattern per line. Multiple K: lines acceptable. 50 | 51 | 52 | Maintainers 53 | ----------- 54 | M: Paolo Bonzini 55 | M: Radim Krčmář 56 | L: kvm@vger.kernel.org 57 | T: git://git.kernel.org/pub/scm/virt/kvm/kvm-unit-tests.git 58 | 59 | Architecture Specific Code: 60 | --------------------------- 61 | 62 | ARM 63 | M: Drew Jones 64 | L: kvm@vger.kernel.org 65 | L: kvmarm@lists.cs.columbia.edu 66 | F: arm/* 67 | F: lib/arm/* 68 | F: lib/arm64/* 69 | 70 | POWERPC 71 | M: Laurent Vivier 72 | M: Thomas Huth 73 | L: kvm@vger.kernel.org 74 | L: kvm-ppc@vger.kernel.org 75 | F: powerpc/* 76 | F: lib/powerpc/* 77 | F: lib/ppc64/* 78 | 79 | X86 80 | M: Paolo Bonzini 81 | M: Radim Krčmář 82 | L: kvm@vger.kernel.org 83 | F: x86/* 84 | F: lib/x86/* 85 | -------------------------------------------------------------------------------- /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/kvm-unit-tests/lib/argv.c: -------------------------------------------------------------------------------- 1 | #include "libcflat.h" 2 | #include "auxinfo.h" 3 | 4 | int __argc; 5 | char *__args; 6 | char *__argv[100]; 7 | char *__environ[200]; 8 | 9 | char **environ = __environ; 10 | 11 | static char args_copy[1000]; 12 | static char *copy_ptr = args_copy; 13 | 14 | #define isblank(c) ((c) == ' ' || (c) == '\t') 15 | #define isalpha(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z') || (c) == '_') 16 | #define isalnum(c) (isalpha(c) || ((c) >= '0' && (c) <= '9')) 17 | 18 | static char *skip_blanks(char *p) 19 | { 20 | while (isblank(*p)) 21 | ++p; 22 | return p; 23 | } 24 | 25 | void __setup_args(void) 26 | { 27 | char *args = __args; 28 | char **argv = __argv + __argc; 29 | 30 | while (*(args = skip_blanks(args)) != '\0') { 31 | *argv++ = copy_ptr; 32 | while (*args != '\0' && !isblank(*args)) 33 | *copy_ptr++ = *args++; 34 | *copy_ptr++ = '\0'; 35 | } 36 | __argc = argv - __argv; 37 | } 38 | 39 | void setup_args(char *args) 40 | { 41 | if (!args) 42 | return; 43 | 44 | __args = args; 45 | __setup_args(); 46 | } 47 | 48 | void setup_args_progname(char *args) 49 | { 50 | __argv[0] = copy_ptr; 51 | strcpy(__argv[0], auxinfo.progname); 52 | copy_ptr += strlen(auxinfo.progname) + 1; 53 | ++__argc; 54 | if (args) { 55 | __args = args; 56 | __setup_args(); 57 | } 58 | } 59 | 60 | static char *env_eol(char *env) 61 | { 62 | while (*env && *env != '\n') 63 | ++env; 64 | return env; 65 | } 66 | 67 | static char *env_invalid_eol(char *env) 68 | { 69 | char *eol = env_eol(env); 70 | char eol_old = *eol; 71 | 72 | *eol = '\0'; 73 | printf("Invalid environment variable: %s\n", env); 74 | *eol = eol_old; 75 | return eol; 76 | } 77 | 78 | static char *env_next(char *env) 79 | { 80 | char *p; 81 | 82 | if (!*env) 83 | return env; 84 | 85 | if (isalpha(*env)) { 86 | bool invalid = false; 87 | 88 | p = env + 1; 89 | while (*p && *p != '=' && *p != '\n') { 90 | if (!isalnum(*p)) 91 | invalid = true; 92 | ++p; 93 | } 94 | 95 | if (*p != '=') 96 | invalid = true; 97 | 98 | if (invalid) { 99 | env = env_invalid_eol(env); 100 | return *env ? env_next(env + 1) : env; 101 | } 102 | return env; 103 | } 104 | 105 | p = env; 106 | while (isblank(*p)) 107 | ++p; 108 | 109 | if (*p == '\n') 110 | return env_next(p + 1); 111 | 112 | if (*p == '#') 113 | env = env_eol(env); 114 | else 115 | env = env_invalid_eol(env); 116 | 117 | return *env ? env_next(env + 1) : env; 118 | } 119 | 120 | void setup_env(char *env, int size) 121 | { 122 | char *eof = env + size, *p = env; 123 | bool newline = false; 124 | int i = 0; 125 | 126 | while (*p) 127 | ++p; 128 | if (p == eof) 129 | newline = true; 130 | 131 | while (env < eof) { 132 | if (newline) 133 | env = env_next(env); 134 | if (!*env || env >= eof) 135 | break; 136 | __environ[i++] = env; 137 | while (env < eof && *env && !(newline && *env == '\n')) 138 | ++env; 139 | *env++ = '\0'; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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) 2014, Red Hat Inc, Andrew Jones 8 | * 9 | * This work is licensed under the terms of the GNU LGPL, 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/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/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 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/asm-generic/spinlock.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASM_GENERIC_SPINLOCK_H_ 2 | #define _ASM_GENERIC_SPINLOCK_H_ 3 | #error need architecture specific asm/spinlock.h 4 | #endif 5 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/auxinfo.c: -------------------------------------------------------------------------------- 1 | #include "auxinfo.h" 2 | struct auxinfo auxinfo = { PROGNAME }; 3 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/auxinfo.h: -------------------------------------------------------------------------------- 1 | #ifndef _AUXINFO_H_ 2 | #define _AUXINFO_H_ 3 | struct auxinfo { 4 | const char *progname; 5 | }; 6 | 7 | /* No extern! Define a common symbol. */ 8 | struct auxinfo auxinfo; 9 | #endif 10 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/bitops.h: -------------------------------------------------------------------------------- 1 | #ifndef _BITOPS_H_ 2 | #define _BITOPS_H_ 3 | 4 | /* 5 | * Adapated from 6 | * include/linux/bitops.h 7 | * 8 | * Copyright (C) 2015, Red Hat Inc, Andrew Jones 9 | * 10 | * This work is licensed under the terms of the GNU LGPL, 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/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/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/kvm-unit-tests/lib/errata.h: -------------------------------------------------------------------------------- 1 | #ifndef _ERRATA_H_ 2 | #define _ERRATA_H_ 3 | 4 | #define _ERRATA(erratum) errata("ERRATA_" # erratum) 5 | #define ERRATA(erratum) _ERRATA(erratum) 6 | 7 | #define _ERRATA_RELAXED(erratum) errata_relaxed("ERRATA_" # erratum) 8 | #define ERRATA_RELAXED(erratum) _ERRATA_RELAXED(erratum) 9 | 10 | static inline bool errata(const char *erratum) 11 | { 12 | char *s = getenv(erratum); 13 | 14 | return s && (*s == '1' || *s == 'y' || *s == 'Y'); 15 | } 16 | 17 | static inline bool errata_relaxed(const char *erratum) 18 | { 19 | char *s = getenv(erratum); 20 | 21 | return !(s && (*s == '0' || *s == 'n' || *s == 'N')); 22 | } 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/kvm-unit-tests/lib/libfdt/fdt_empty_tree.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libfdt - Flat Device Tree manipulation 3 | * Copyright (C) 2012 David Gibson, IBM Corporation. 4 | * 5 | * libfdt is dual licensed: you can use it either under the terms of 6 | * the GPL, or the BSD license, at your option. 7 | * 8 | * a) This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License as 10 | * published by the Free Software Foundation; either version 2 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public 19 | * License along with this library; if not, write to the Free 20 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 21 | * MA 02110-1301 USA 22 | * 23 | * Alternatively, 24 | * 25 | * b) Redistribution and use in source and binary forms, with or 26 | * without modification, are permitted provided that the following 27 | * conditions are met: 28 | * 29 | * 1. Redistributions of source code must retain the above 30 | * copyright notice, this list of conditions and the following 31 | * disclaimer. 32 | * 2. Redistributions in binary form must reproduce the above 33 | * copyright notice, this list of conditions and the following 34 | * disclaimer in the documentation and/or other materials 35 | * provided with the distribution. 36 | * 37 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 38 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 39 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 40 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 41 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 42 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 43 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 44 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 45 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 47 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 48 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 49 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 50 | */ 51 | #include "libfdt_env.h" 52 | 53 | #include 54 | #include 55 | 56 | #include "libfdt_internal.h" 57 | 58 | int fdt_create_empty_tree(void *buf, int bufsize) 59 | { 60 | int err; 61 | 62 | err = fdt_create(buf, bufsize); 63 | if (err) 64 | return err; 65 | 66 | err = fdt_finish_reservemap(buf); 67 | if (err) 68 | return err; 69 | 70 | err = fdt_begin_node(buf, ""); 71 | if (err) 72 | return err; 73 | 74 | err = fdt_end_node(buf); 75 | if (err) 76 | return err; 77 | 78 | err = fdt_finish(buf); 79 | if (err) 80 | return err; 81 | 82 | return fdt_open_into(buf, buf, bufsize); 83 | } 84 | 85 | -------------------------------------------------------------------------------- /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/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/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 0x%" PRIx64 " size 0x%lu off 0x%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/kvm-unit-tests/lib/pci-edu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Edu PCI device header. 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 | * Edu device is a virtualized device in QEMU. Please refer to 13 | * docs/specs/edu.txt in QEMU repository for EDU device manual. 14 | */ 15 | #ifndef __PCI_EDU_H__ 16 | #define __PCI_EDU_H__ 17 | 18 | #include "pci.h" 19 | #include "asm/io.h" 20 | 21 | #define PCI_VENDOR_ID_QEMU 0x1234 22 | #define PCI_DEVICE_ID_EDU 0x11e8 23 | 24 | /* The only bar used by EDU device */ 25 | #define EDU_BAR 0 26 | #define EDU_MAGIC 0xed 27 | #define EDU_VERSION 0x100 28 | #define EDU_DMA_BUF_SIZE (1 << 20) 29 | #define EDU_INPUT_BUF_SIZE 256 30 | 31 | #define EDU_REG_ID 0x0 32 | #define EDU_REG_ALIVE 0x4 33 | #define EDU_REG_FACTORIAL 0x8 34 | #define EDU_REG_STATUS 0x20 35 | #define EDU_REG_INTR_STATUS 0x24 36 | #define EDU_REG_INTR_RAISE 0x60 37 | #define EDU_REG_INTR_ACK 0x64 38 | #define EDU_REG_DMA_SRC 0x80 39 | #define EDU_REG_DMA_DST 0x88 40 | #define EDU_REG_DMA_COUNT 0x90 41 | #define EDU_REG_DMA_CMD 0x98 42 | 43 | #define EDU_CMD_DMA_START 0x01 44 | #define EDU_CMD_DMA_FROM 0x02 45 | #define EDU_CMD_DMA_TO 0x00 46 | 47 | #define EDU_STATUS_FACTORIAL 0x1 48 | #define EDU_STATUS_INT_ENABLE 0x80 49 | 50 | #define EDU_DMA_START 0x40000 51 | #define EDU_DMA_SIZE_MAX 4096 52 | 53 | struct pci_edu_dev { 54 | struct pci_dev pci_dev; 55 | volatile void *reg_base; 56 | }; 57 | 58 | #define edu_reg(d, r) (volatile void *)((d)->reg_base + (r)) 59 | 60 | static inline uint64_t edu_reg_readq(struct pci_edu_dev *dev, int reg) 61 | { 62 | return __raw_readq(edu_reg(dev, reg)); 63 | } 64 | 65 | static inline uint32_t edu_reg_readl(struct pci_edu_dev *dev, int reg) 66 | { 67 | return __raw_readl(edu_reg(dev, reg)); 68 | } 69 | 70 | static inline void edu_reg_writeq(struct pci_edu_dev *dev, int reg, 71 | uint64_t val) 72 | { 73 | __raw_writeq(val, edu_reg(dev, reg)); 74 | } 75 | 76 | static inline void edu_reg_writel(struct pci_edu_dev *dev, int reg, 77 | uint32_t val) 78 | { 79 | __raw_writel(val, edu_reg(dev, reg)); 80 | } 81 | 82 | bool edu_init(struct pci_edu_dev *dev); 83 | void edu_dma(struct pci_edu_dev *dev, iova_t iova, 84 | size_t size, unsigned int dev_offset, bool from_device); 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /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/setjmp.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCFLAT_SETJMP_H 2 | #define LIBCFLAT_SETJMP_H 1 3 | 4 | typedef struct jmp_buf_tag { 5 | long int regs[8]; 6 | } jmp_buf[1]; 7 | 8 | extern int setjmp (struct jmp_buf_tag env[1]); 9 | extern void longjmp (struct jmp_buf_tag env[1], int val) 10 | __attribute__ ((__noreturn__)); 11 | 12 | #endif /* setjmp.h */ 13 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/stack.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX_DEPTH 20 5 | 6 | static void print_stack(const void **return_addrs, int depth, 7 | bool top_is_return_address) 8 | { 9 | int i = 0; 10 | 11 | printf("\tSTACK:"); 12 | 13 | /* @addr indicates a non-return address, as expected by the stack 14 | * pretty printer script. */ 15 | if (depth > 0 && !top_is_return_address) { 16 | printf(" @%lx", (unsigned long) return_addrs[0]); 17 | i++; 18 | } 19 | 20 | for (; i < depth; i++) { 21 | printf(" %lx", (unsigned long) return_addrs[i]); 22 | } 23 | printf("\n"); 24 | } 25 | 26 | void dump_stack(void) 27 | { 28 | const void *return_addrs[MAX_DEPTH]; 29 | int depth; 30 | 31 | depth = backtrace(return_addrs, MAX_DEPTH); 32 | print_stack(&return_addrs[1], depth ? depth - 1 : 0, true); 33 | } 34 | 35 | void dump_frame_stack(const void *instruction, const void *frame) 36 | { 37 | const void *return_addrs[MAX_DEPTH]; 38 | int depth; 39 | 40 | return_addrs[0] = instruction; 41 | depth = backtrace_frame(frame, &return_addrs[1], MAX_DEPTH - 1); 42 | print_stack(return_addrs, depth + 1, false); 43 | } 44 | 45 | #ifndef HAVE_ARCH_BACKTRACE 46 | int backtrace(const void **return_addrs, int max_depth) 47 | { 48 | static int walking; 49 | int depth = 0; 50 | void *addr; 51 | 52 | if (walking) { 53 | printf("RECURSIVE STACK WALK!!!\n"); 54 | return 0; 55 | } 56 | walking = 1; 57 | 58 | /* __builtin_return_address requires a compile-time constant argument */ 59 | #define GET_RETURN_ADDRESS(i) \ 60 | if (max_depth == i) \ 61 | goto done; \ 62 | addr = __builtin_return_address(i); \ 63 | if (!addr) \ 64 | goto done; \ 65 | return_addrs[i] = __builtin_extract_return_addr(addr); \ 66 | depth = i + 1; \ 67 | 68 | GET_RETURN_ADDRESS(0) 69 | GET_RETURN_ADDRESS(1) 70 | GET_RETURN_ADDRESS(2) 71 | GET_RETURN_ADDRESS(3) 72 | GET_RETURN_ADDRESS(4) 73 | GET_RETURN_ADDRESS(5) 74 | GET_RETURN_ADDRESS(6) 75 | GET_RETURN_ADDRESS(7) 76 | GET_RETURN_ADDRESS(8) 77 | GET_RETURN_ADDRESS(9) 78 | GET_RETURN_ADDRESS(10) 79 | GET_RETURN_ADDRESS(11) 80 | GET_RETURN_ADDRESS(12) 81 | GET_RETURN_ADDRESS(13) 82 | GET_RETURN_ADDRESS(14) 83 | GET_RETURN_ADDRESS(15) 84 | GET_RETURN_ADDRESS(16) 85 | GET_RETURN_ADDRESS(17) 86 | GET_RETURN_ADDRESS(18) 87 | GET_RETURN_ADDRESS(19) 88 | GET_RETURN_ADDRESS(20) 89 | 90 | #undef GET_RETURN_ADDRESS 91 | 92 | done: 93 | walking = 0; 94 | return depth; 95 | } 96 | #endif /* HAVE_ARCH_BACKTRACE */ 97 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/stack.h: -------------------------------------------------------------------------------- 1 | #ifndef _STACK_H_ 2 | #define _STACK_H_ 3 | 4 | #include 5 | #include 6 | 7 | #ifdef HAVE_ARCH_BACKTRACE_FRAME 8 | extern int backtrace_frame(const void *frame, const void **return_addrs, 9 | int max_depth); 10 | #else 11 | static inline int 12 | backtrace_frame(const void *frame __unused, const void **return_addrs __unused, 13 | int max_depth __unused) 14 | { 15 | return 0; 16 | } 17 | #endif 18 | 19 | extern int backtrace(const void **return_addrs, int max_depth); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/string.h: -------------------------------------------------------------------------------- 1 | #ifndef __STRING_H 2 | #define __STRING_H 3 | 4 | extern unsigned long strlen(const char *buf); 5 | extern char *strcat(char *dest, const char *src); 6 | extern char *strcpy(char *dest, const char *src); 7 | extern int strcmp(const char *a, const char *b); 8 | extern int strncmp(const char *a, const char *b, size_t n); 9 | extern char *strchr(const char *s, int c); 10 | extern char *strstr(const char *haystack, const char *needle); 11 | extern void *memset(void *s, int c, size_t n); 12 | extern void *memcpy(void *dest, const void *src, size_t n); 13 | extern int memcmp(const void *s1, const void *s2, size_t n); 14 | extern void *memmove(void *dest, const void *src, size_t n); 15 | extern void *memchr(const void *s, int c, size_t n); 16 | 17 | #endif /* _STRING_H */ 18 | -------------------------------------------------------------------------------- /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 | 8 | int parse_keyval(char *s, long *val) 9 | { 10 | char *p; 11 | 12 | p = strchr(s, '='); 13 | if (!p) 14 | return -1; 15 | 16 | *val = atol(p+1); 17 | return p - s; 18 | } 19 | -------------------------------------------------------------------------------- /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/kvm-unit-tests/lib/virtio-mmio.h: -------------------------------------------------------------------------------- 1 | #ifndef _VIRTIO_MMIO_H_ 2 | #define _VIRTIO_MMIO_H_ 3 | /* 4 | * A minimal implementation of virtio-mmio. Adapted from the Linux Kernel. 5 | * 6 | * Copyright (C) 2014, Red Hat Inc, Andrew Jones 7 | * 8 | * This work is licensed under the terms of the GNU LGPL, version 2. 9 | */ 10 | #include "libcflat.h" 11 | #include "asm/page.h" 12 | #include "virtio.h" 13 | 14 | #define VIRTIO_MMIO_MAGIC_VALUE 0x000 15 | #define VIRTIO_MMIO_VERSION 0x004 16 | #define VIRTIO_MMIO_DEVICE_ID 0x008 17 | #define VIRTIO_MMIO_VENDOR_ID 0x00c 18 | #define VIRTIO_MMIO_HOST_FEATURES 0x010 19 | #define VIRTIO_MMIO_HOST_FEATURES_SEL 0x014 20 | #define VIRTIO_MMIO_GUEST_FEATURES 0x020 21 | #define VIRTIO_MMIO_GUEST_FEATURES_SEL 0x024 22 | #define VIRTIO_MMIO_GUEST_PAGE_SIZE 0x028 23 | #define VIRTIO_MMIO_QUEUE_SEL 0x030 24 | #define VIRTIO_MMIO_QUEUE_NUM_MAX 0x034 25 | #define VIRTIO_MMIO_QUEUE_NUM 0x038 26 | #define VIRTIO_MMIO_QUEUE_ALIGN 0x03c 27 | #define VIRTIO_MMIO_QUEUE_PFN 0x040 28 | #define VIRTIO_MMIO_QUEUE_NOTIFY 0x050 29 | #define VIRTIO_MMIO_INTERRUPT_STATUS 0x060 30 | #define VIRTIO_MMIO_INTERRUPT_ACK 0x064 31 | #define VIRTIO_MMIO_STATUS 0x070 32 | #define VIRTIO_MMIO_CONFIG 0x100 33 | 34 | #define VIRTIO_MMIO_INT_VRING (1 << 0) 35 | #define VIRTIO_MMIO_INT_CONFIG (1 << 1) 36 | 37 | #define VIRTIO_MMIO_VRING_ALIGN PAGE_SIZE 38 | 39 | /* 40 | * The minimum queue size is 2*VIRTIO_MMIO_VRING_ALIGN, which 41 | * means the largest queue num for the minimum queue size is 128, i.e. 42 | * 2*VIRTIO_MMIO_VRING_ALIGN = vring_size(128, VIRTIO_MMIO_VRING_ALIGN), 43 | * where vring_size is 44 | * 45 | * unsigned vring_size(unsigned num, unsigned long align) 46 | * { 47 | * return ((sizeof(struct vring_desc) * num + sizeof(u16) * (3 + num) 48 | * + align - 1) & ~(align - 1)) 49 | * + sizeof(u16) * 3 + sizeof(struct vring_used_elem) * num; 50 | * } 51 | */ 52 | #define VIRTIO_MMIO_QUEUE_SIZE_MIN (2*VIRTIO_MMIO_VRING_ALIGN) 53 | #define VIRTIO_MMIO_QUEUE_NUM_MIN 128 54 | 55 | #define to_virtio_mmio_device(vdev_ptr) \ 56 | container_of(vdev_ptr, struct virtio_mmio_device, vdev) 57 | 58 | struct virtio_mmio_device { 59 | struct virtio_device vdev; 60 | void *base; 61 | }; 62 | 63 | extern struct virtio_device *virtio_mmio_bind(u32 devid); 64 | 65 | #endif /* _VIRTIO_MMIO_H_ */ 66 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | #ifdef __x86_64__ 35 | #define PAGE_LEVEL 4 36 | #define PGDIR_WIDTH 9 37 | #define PGDIR_MASK 511 38 | #else 39 | #define PAGE_LEVEL 2 40 | #define PGDIR_WIDTH 10 41 | #define PGDIR_MASK 1023 42 | #endif 43 | 44 | #define PGDIR_BITS(lvl) (((lvl) - 1) * PGDIR_WIDTH + PAGE_SHIFT) 45 | #define PGDIR_OFFSET(va, lvl) (((va) >> PGDIR_BITS(lvl)) & PGDIR_MASK) 46 | 47 | #endif /* !__ASSEMBLY__ */ 48 | #endif 49 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/asm/pci.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_PCI_H 2 | #define ASM_PCI_H 3 | /* 4 | * Copyright (C) 2013, Red Hat Inc, Michael S. Tsirkin 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/kvm-unit-tests/lib/x86/asm/spinlock.h: -------------------------------------------------------------------------------- 1 | #ifndef __ASM_SPINLOCK_H 2 | #define __ASM_SPINLOCK_H 3 | 4 | struct spinlock { 5 | int v; 6 | }; 7 | 8 | void spin_lock(struct spinlock *lock); 9 | void spin_unlock(struct spinlock *lock); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/asm/stack.h: -------------------------------------------------------------------------------- 1 | #ifndef _X86ASM_STACK_H_ 2 | #define _X86ASM_STACK_H_ 3 | 4 | #ifndef _STACK_H_ 5 | #error Do not directly include . Just use . 6 | #endif 7 | 8 | #define HAVE_ARCH_BACKTRACE_FRAME 9 | #define HAVE_ARCH_BACKTRACE 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/lib/x86/fwcfg.c: -------------------------------------------------------------------------------- 1 | #include "fwcfg.h" 2 | #include "smp.h" 3 | 4 | static struct spinlock lock; 5 | 6 | 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/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/kvm-unit-tests/lib/x86/io.c: -------------------------------------------------------------------------------- 1 | #include "libcflat.h" 2 | #include "vm.h" 3 | #include "smp.h" 4 | #include "asm/io.h" 5 | #include "asm/page.h" 6 | #ifndef USE_SERIAL 7 | #define USE_SERIAL 8 | #endif 9 | 10 | static struct spinlock lock; 11 | static int serial_iobase = 0x3f8; 12 | static int serial_inited = 0; 13 | 14 | static void serial_outb(char ch) 15 | { 16 | u8 lsr; 17 | 18 | do { 19 | lsr = inb(serial_iobase + 0x05); 20 | } while (!(lsr & 0x20)); 21 | 22 | outb(ch, serial_iobase + 0x00); 23 | } 24 | 25 | static void serial_init(void) 26 | { 27 | u8 lcr; 28 | 29 | /* set DLAB */ 30 | lcr = inb(serial_iobase + 0x03); 31 | lcr |= 0x80; 32 | outb(lcr, serial_iobase + 0x03); 33 | 34 | /* set baud rate to 115200 */ 35 | outb(0x01, serial_iobase + 0x00); 36 | outb(0x00, serial_iobase + 0x01); 37 | 38 | /* clear DLAB */ 39 | lcr = inb(serial_iobase + 0x03); 40 | lcr &= ~0x80; 41 | outb(lcr, serial_iobase + 0x03); 42 | } 43 | 44 | static void print_serial(const char *buf) 45 | { 46 | unsigned long len = strlen(buf); 47 | #ifdef USE_SERIAL 48 | unsigned long i; 49 | if (!serial_inited) { 50 | serial_init(); 51 | serial_inited = 1; 52 | } 53 | 54 | for (i = 0; i < len; i++) { 55 | serial_outb(buf[i]); 56 | } 57 | #else 58 | asm volatile ("rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1)); 59 | #endif 60 | } 61 | 62 | void puts(const char *s) 63 | { 64 | spin_lock(&lock); 65 | print_serial(s); 66 | spin_unlock(&lock); 67 | } 68 | 69 | void exit(int code) 70 | { 71 | #ifdef USE_SERIAL 72 | static const char shutdown_str[8] = "Shutdown"; 73 | int i; 74 | 75 | /* test device exit (with status) */ 76 | outl(code, 0xf4); 77 | 78 | /* if that failed, try the Bochs poweroff port */ 79 | for (i = 0; i < 8; i++) { 80 | outb(shutdown_str[i], 0x8900); 81 | } 82 | #else 83 | asm volatile("out %0, %1" : : "a"(code), "d"((short)0xf4)); 84 | #endif 85 | } 86 | 87 | void __iomem *ioremap(phys_addr_t phys_addr, size_t size) 88 | { 89 | phys_addr_t base = phys_addr & PAGE_MASK; 90 | phys_addr_t offset = phys_addr - base; 91 | 92 | /* 93 | * The kernel sets PTEs for an ioremap() with page cache disabled, 94 | * but we do not do that right now. It would make sense that I/O 95 | * mappings would be uncached - and may help us find bugs when we 96 | * properly map that way. 97 | */ 98 | return vmap(phys_addr, size) + offset; 99 | } 100 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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/lib/x86/smp.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "smp.h" 4 | #include "apic.h" 5 | #include "fwcfg.h" 6 | #include "desc.h" 7 | 8 | #define IPI_VECTOR 0x20 9 | 10 | typedef void (*ipi_function_type)(void *data); 11 | 12 | static struct spinlock ipi_lock; 13 | static volatile ipi_function_type ipi_function; 14 | static void *volatile ipi_data; 15 | static volatile int ipi_done; 16 | static volatile bool ipi_wait; 17 | static int _cpu_count; 18 | 19 | static __attribute__((used)) void ipi() 20 | { 21 | void (*function)(void *data) = ipi_function; 22 | void *data = ipi_data; 23 | bool wait = ipi_wait; 24 | 25 | if (!wait) { 26 | ipi_done = 1; 27 | apic_write(APIC_EOI, 0); 28 | } 29 | function(data); 30 | if (wait) { 31 | ipi_done = 1; 32 | apic_write(APIC_EOI, 0); 33 | } 34 | } 35 | 36 | asm ( 37 | "ipi_entry: \n" 38 | " call ipi \n" 39 | #ifndef __x86_64__ 40 | " iret" 41 | #else 42 | " iretq" 43 | #endif 44 | ); 45 | 46 | void spin_lock(struct spinlock *lock) 47 | { 48 | int v = 1; 49 | 50 | do { 51 | asm volatile ("xchg %1, %0" : "+m"(lock->v), "+r"(v)); 52 | } while (v); 53 | asm volatile ("" : : : "memory"); 54 | } 55 | 56 | void spin_unlock(struct spinlock *lock) 57 | { 58 | asm volatile ("" : : : "memory"); 59 | lock->v = 0; 60 | } 61 | 62 | int cpu_count(void) 63 | { 64 | return _cpu_count; 65 | } 66 | 67 | int smp_id(void) 68 | { 69 | unsigned id; 70 | 71 | asm ("mov %%gs:0, %0" : "=r"(id)); 72 | return id; 73 | } 74 | 75 | static void setup_smp_id(void *data) 76 | { 77 | asm ("mov %0, %%gs:0" : : "r"(apic_id()) : "memory"); 78 | } 79 | 80 | static void __on_cpu(int cpu, void (*function)(void *data), void *data, 81 | int wait) 82 | { 83 | spin_lock(&ipi_lock); 84 | if (cpu == smp_id()) 85 | function(data); 86 | else { 87 | ipi_done = 0; 88 | ipi_function = function; 89 | ipi_data = data; 90 | ipi_wait = wait; 91 | apic_icr_write(APIC_INT_ASSERT | APIC_DEST_PHYSICAL | APIC_DM_FIXED 92 | | IPI_VECTOR, 93 | cpu); 94 | while (!ipi_done) 95 | ; 96 | } 97 | spin_unlock(&ipi_lock); 98 | } 99 | 100 | void on_cpu(int cpu, void (*function)(void *data), void *data) 101 | { 102 | __on_cpu(cpu, function, data, 1); 103 | } 104 | 105 | void on_cpu_async(int cpu, void (*function)(void *data), void *data) 106 | { 107 | __on_cpu(cpu, function, data, 0); 108 | } 109 | 110 | 111 | void smp_init(void) 112 | { 113 | int i; 114 | void ipi_entry(void); 115 | 116 | _cpu_count = fwcfg_get_nb_cpus(); 117 | 118 | setup_idt(); 119 | set_idt_entry(IPI_VECTOR, ipi_entry, 0); 120 | 121 | setup_smp_id(0); 122 | for (i = 1; i < cpu_count(); ++i) 123 | on_cpu(i, setup_smp_id, 0); 124 | 125 | } 126 | -------------------------------------------------------------------------------- /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 | void on_cpu(int cpu, void (*function)(void *data), void *data); 10 | void on_cpu_async(int cpu, void (*function)(void *data), void *data); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /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/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 | unsigned long *get_pte(unsigned long *cr3, void *virt); 18 | unsigned long *install_pte(unsigned long *cr3, 19 | int pte_level, 20 | void *virt, 21 | unsigned long pte, 22 | unsigned long *pt_page); 23 | 24 | void *alloc_page(); 25 | void free_page(void *page); 26 | 27 | unsigned long *install_large_page(unsigned long *cr3,unsigned long phys, 28 | void *virt); 29 | unsigned long *install_page(unsigned long *cr3, unsigned long phys, void *virt); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/run.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | var V86 = require("../../build/libv86.js").V86; 5 | var fs = require("fs"); 6 | 7 | function readfile(path) 8 | { 9 | return new Uint8Array(fs.readFileSync(path)).buffer; 10 | } 11 | 12 | function Loader(path) 13 | { 14 | this.buffer = readfile(path); 15 | this.byteLength = this.buffer.byteLength; 16 | } 17 | 18 | Loader.prototype.load = function() 19 | { 20 | this.onload && this.onload({}); 21 | }; 22 | 23 | var bios = readfile(__dirname + "/../../bios/seabios.bin"); 24 | var vga_bios = readfile(__dirname + "/../../bios/vgabios.bin"); 25 | 26 | var emulator = new V86({ 27 | bios: { buffer: bios }, 28 | vga_bios: { buffer: vga_bios }, 29 | multiboot: new Loader(process.argv[2]), 30 | autostart: true, 31 | memory_size: 64 * 1024 * 1024, 32 | }); 33 | 34 | emulator.bus.register("emulator-started", function() 35 | { 36 | emulator.v86.cpu.io.register_write_consecutive(0xF4, this, 37 | function(value) 38 | { 39 | console.log("Test exited with code " + value); 40 | process.exit(value); 41 | }, 42 | function() {}, 43 | function() {}, 44 | function() {}); 45 | }); 46 | 47 | emulator.add_listener("serial0-output-char", function(chr) 48 | { 49 | process.stdout.write(chr); 50 | }); 51 | 52 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/Makefile: -------------------------------------------------------------------------------- 1 | include $(TEST_DIR)/Makefile.$(ARCH) 2 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/Makefile.common: -------------------------------------------------------------------------------- 1 | #This is a make file with common rules for both x86 & x86-64 2 | 3 | all: test_cases 4 | 5 | cflatobjs += lib/pci.o 6 | cflatobjs += lib/pci-edu.o 7 | cflatobjs += lib/x86/setup.o 8 | cflatobjs += lib/x86/io.o 9 | cflatobjs += lib/x86/smp.o 10 | cflatobjs += lib/x86/vm.o 11 | cflatobjs += lib/x86/fwcfg.o 12 | cflatobjs += lib/x86/apic.o 13 | cflatobjs += lib/x86/atomic.o 14 | cflatobjs += lib/x86/desc.o 15 | cflatobjs += lib/x86/isr.o 16 | cflatobjs += lib/x86/acpi.o 17 | cflatobjs += lib/x86/stack.o 18 | 19 | $(libcflat): LDFLAGS += -nostdlib 20 | $(libcflat): CFLAGS += -ffreestanding -I lib 21 | 22 | CFLAGS += -m$(bits) 23 | CFLAGS += -O1 24 | 25 | # stack.o relies on frame pointers. 26 | KEEP_FRAME_POINTER := y 27 | 28 | libgcc := $(shell $(CC) -m$(bits) --print-libgcc-file-name) 29 | 30 | # We want to keep intermediate file: %.elf and %.o 31 | .PRECIOUS: %.elf %.o 32 | 33 | FLATLIBS = lib/libcflat.a $(libgcc) 34 | %.elf: %.o $(FLATLIBS) x86/flat.lds $(cstart.o) 35 | $(CC) $(CFLAGS) -nostdlib -o $@ -Wl,-T,x86/flat.lds \ 36 | $(filter %.o, $^) $(FLATLIBS) 37 | 38 | %.flat: %.elf 39 | $(OBJCOPY) -O elf32-i386 $^ $@ 40 | 41 | tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \ 42 | $(TEST_DIR)/smptest.flat $(TEST_DIR)/port80.flat \ 43 | $(TEST_DIR)/realmode.flat $(TEST_DIR)/msr.flat \ 44 | $(TEST_DIR)/hypercall.flat $(TEST_DIR)/sieve.flat \ 45 | $(TEST_DIR)/kvmclock_test.flat $(TEST_DIR)/eventinj.flat \ 46 | $(TEST_DIR)/s3.flat $(TEST_DIR)/pmu.flat $(TEST_DIR)/setjmp.flat \ 47 | $(TEST_DIR)/tsc_adjust.flat $(TEST_DIR)/asyncpf.flat \ 48 | $(TEST_DIR)/init.flat $(TEST_DIR)/smap.flat \ 49 | $(TEST_DIR)/hyperv_synic.flat $(TEST_DIR)/hyperv_stimer.flat \ 50 | 51 | ifdef API 52 | tests-common += api/api-sample 53 | tests-common += api/dirty-log 54 | tests-common += api/dirty-log-perf 55 | endif 56 | 57 | test_cases: $(tests-common) $(tests) 58 | 59 | $(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding -I lib -I lib/x86 60 | 61 | $(TEST_DIR)/realmode.elf: $(TEST_DIR)/realmode.o 62 | $(CC) -m32 -nostdlib -o $@ -Wl,-T,$(TEST_DIR)/realmode.lds $^ 63 | 64 | $(TEST_DIR)/realmode.o: bits = 32 65 | 66 | $(TEST_DIR)/kvmclock_test.elf: $(TEST_DIR)/kvmclock.o 67 | 68 | $(TEST_DIR)/hyperv_synic.elf: $(TEST_DIR)/hyperv.o 69 | 70 | $(TEST_DIR)/hyperv_stimer.elf: $(TEST_DIR)/hyperv.o 71 | 72 | arch_clean: 73 | $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \ 74 | $(TEST_DIR)/.*.d lib/x86/.*.d 75 | 76 | api/%.o: CFLAGS += -m32 77 | 78 | api/%: LDLIBS += -lstdc++ -lboost_thread -lpthread -lrt 79 | api/%: LDFLAGS += -m32 80 | 81 | api/libapi.a: api/kvmxx.o api/identity.o api/exception.o api/memmap.o 82 | $(AR) rcs $@ $^ 83 | 84 | api/api-sample: api/api-sample.o api/libapi.a 85 | 86 | api/dirty-log: api/dirty-log.o api/libapi.a 87 | 88 | api/dirty-log-perf: api/dirty-log-perf.o api/libapi.a 89 | -------------------------------------------------------------------------------- /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 $(TEST_DIR)/Makefile.common 34 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/Makefile.x86_64: -------------------------------------------------------------------------------- 1 | cstart.o = $(TEST_DIR)/cstart64.o 2 | bits = 64 3 | ldarch = elf64-x86-64 4 | 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)/svm.flat 16 | tests += $(TEST_DIR)/vmx.flat 17 | tests += $(TEST_DIR)/tscdeadline_latency.flat 18 | tests += $(TEST_DIR)/intel-iommu.flat 19 | 20 | include $(TEST_DIR)/Makefile.common 21 | 22 | $(TEST_DIR)/hyperv_clock.elf: $(TEST_DIR)/hyperv_clock.o 23 | 24 | $(TEST_DIR)/vmx.elf: $(TEST_DIR)/vmx_tests.o 25 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/README: -------------------------------------------------------------------------------- 1 | 2 | Tests for the x86 architecture are run as kernel images for qemu that support 3 | multiboot format. The tests use an infrastructure called from the bios code. 4 | The infrastructure initialize the system/cpus, switches to long-mode, and 5 | calls the 'main' function of the individual test. Tests use a qemu virtual 6 | test device, named testdev, for services like printing, exiting, querying 7 | memory size, etc. See file docs/testdev.txt for more details. 8 | 9 | Examples of a test invocation: 10 | These invocations run the msr test case and outputs to stdio. 11 | 12 | Using qemu-kvm: 13 | 14 | qemu-kvm -device testdev,chardev=testlog \ 15 | -chardev file,id=testlog,path=msr.out \ 16 | -serial stdio -kernel ./x86/msr.flat 17 | 18 | Using qemu (supported since qemu 1.3): 19 | 20 | qemu-system-x86_64 -enable-kvm -device pc-testdev -serial stdio \ 21 | -device isa-debug-exit,iobase=0xf4,iosize=0x4 \ 22 | -kernel ./x86/msr.flat 23 | 24 | Tests in this directory and what they do: 25 | access: lots of page table related access (pte/pde) (read/write) 26 | apic: enable x2apic, self ipi, ioapic intr, ioapic simultaneous 27 | emulator: move to/from regs, cmps, push, pop, to/from cr8, smsw and lmsw 28 | hypercall: intel and amd hypercall insn 29 | msr: write to msr (only KERNEL_GS_BASE for now) 30 | port80: lots of out to port 80 31 | realmode: goes back to realmode, shld, push/pop, mov immediate, cmp 32 | immediate, add immediate, io, eflags instructions 33 | (clc, cli, etc.), jcc short, jcc near, call, long jmp, xchg 34 | sieve: heavy memory access with no paging and with paging static and 35 | with paging vmalloc'ed 36 | smptest: run smp_id() on every cpu and compares return value to number 37 | tsc: write to tsc(0) and write to tsc(100000000000) and read it back 38 | vmexit: long loops for each: cpuid, vmcall, mov_from_cr8, mov_to_cr8, 39 | inl_pmtimer, ipi, ipi+halt 40 | kvmclock_test: test of wallclock, monotonic cycle and performance of kvmclock 41 | pcid: basic functionality test of PCID/INVPCID feature 42 | 43 | Legacy notes: 44 | The exit status of the binary is inconsistent; with qemu-system, after 45 | the unit-test is done, the exit status of qemu is 1, different from the 46 | 'old style' qemu-kvm, whose exit status in successful completion is 0. 47 | The run script converts the qemu-system exit status to 0 (SUCCESS), and 48 | treats the legacy exit status of 0 as an error, converting it to an exit 49 | status of 1. 50 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/asyncpf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Async PF test. For the test to actually do anything it needs to be started 3 | * in memory cgroup with 512M of memory and with more then 1G memory provided 4 | * to the guest. 5 | * 6 | * To create cgroup do as root: 7 | * mkdir /dev/cgroup 8 | * mount -t cgroup none -omemory /dev/cgroup 9 | * chmod a+rxw /dev/cgroup/ 10 | * 11 | * From a shell you will start qemu from: 12 | * mkdir /dev/cgroup/1 13 | * echo $$ > /dev/cgroup/1/tasks 14 | * echo 512M > /dev/cgroup/1/memory.limit_in_bytes 15 | * 16 | */ 17 | #include "x86/msr.h" 18 | #include "x86/processor.h" 19 | #include "x86/apic-defs.h" 20 | #include "x86/apic.h" 21 | #include "x86/desc.h" 22 | #include "x86/isr.h" 23 | #include "x86/vm.h" 24 | 25 | #include "libcflat.h" 26 | #include 27 | 28 | #define KVM_PV_REASON_PAGE_NOT_PRESENT 1 29 | #define KVM_PV_REASON_PAGE_READY 2 30 | 31 | #define MSR_KVM_ASYNC_PF_EN 0x4b564d02 32 | 33 | #define KVM_ASYNC_PF_ENABLED (1 << 0) 34 | #define KVM_ASYNC_PF_SEND_ALWAYS (1 << 1) 35 | 36 | volatile uint32_t apf_reason __attribute__((aligned(64))); 37 | char *buf; 38 | volatile uint64_t i; 39 | volatile uint64_t phys; 40 | 41 | static inline uint32_t get_apf_reason(void) 42 | { 43 | uint32_t r = apf_reason; 44 | apf_reason = 0; 45 | return r; 46 | } 47 | 48 | static void pf_isr(struct ex_regs *r) 49 | { 50 | void* virt = (void*)((ulong)(buf+i) & ~(PAGE_SIZE-1)); 51 | uint32_t reason = get_apf_reason(); 52 | 53 | switch (reason) { 54 | case 0: 55 | report("unexpected #PF at %p", false, read_cr2()); 56 | break; 57 | case KVM_PV_REASON_PAGE_NOT_PRESENT: 58 | phys = virt_to_phys_cr3(virt); 59 | install_pte(phys_to_virt(read_cr3()), 1, virt, phys, 0); 60 | write_cr3(read_cr3()); 61 | report("Got not present #PF token %x virt addr %p phys addr %p", 62 | true, read_cr2(), virt, phys); 63 | while(phys) { 64 | safe_halt(); /* enables irq */ 65 | irq_disable(); 66 | } 67 | break; 68 | case KVM_PV_REASON_PAGE_READY: 69 | report("Got present #PF token %x", true, read_cr2()); 70 | if ((uint32_t)read_cr2() == ~0) 71 | break; 72 | install_pte(phys_to_virt(read_cr3()), 1, virt, phys | PT_PRESENT_MASK | PT_WRITABLE_MASK, 0); 73 | write_cr3(read_cr3()); 74 | phys = 0; 75 | break; 76 | default: 77 | report("unexpected async pf reason %d", false, reason); 78 | break; 79 | } 80 | } 81 | 82 | #define MEM 1ull*1024*1024*1024 83 | 84 | int main(int ac, char **av) 85 | { 86 | int loop = 2; 87 | 88 | setup_vm(); 89 | setup_idt(); 90 | printf("install handler\n"); 91 | handle_exception(14, pf_isr); 92 | apf_reason = 0; 93 | printf("enable async pf\n"); 94 | wrmsr(MSR_KVM_ASYNC_PF_EN, virt_to_phys((void*)&apf_reason) | 95 | KVM_ASYNC_PF_SEND_ALWAYS | KVM_ASYNC_PF_ENABLED); 96 | printf("alloc memory\n"); 97 | buf = vmalloc(MEM); 98 | irq_enable(); 99 | while(loop--) { 100 | printf("start loop\n"); 101 | /* access a lot of memory to make host swap it out */ 102 | for (i=0; i < MEM; i+=4096) 103 | buf[i] = 1; 104 | printf("end loop\n"); 105 | } 106 | irq_disable(); 107 | 108 | return report_summary(); 109 | } 110 | -------------------------------------------------------------------------------- /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/kvm-unit-tests/x86/flat.lds: -------------------------------------------------------------------------------- 1 | SECTIONS 2 | { 3 | . = 4M + SIZEOF_HEADERS; 4 | stext = .; 5 | .text : { *(.init) *(.text) *(.text.*) } 6 | . = ALIGN(4K); 7 | .data : { 8 | *(.data) 9 | exception_table_start = .; 10 | *(.data.ex) 11 | exception_table_end = .; 12 | } 13 | . = ALIGN(16); 14 | .rodata : { *(.rodata) } 15 | . = ALIGN(16); 16 | .bss : { *(.bss) } 17 | . = ALIGN(4K); 18 | edata = .; 19 | } 20 | 21 | ENTRY(start) 22 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/hypercall.c: -------------------------------------------------------------------------------- 1 | #include "libcflat.h" 2 | #include "vm.h" 3 | #include "desc.h" 4 | 5 | #define KVM_HYPERCALL_INTEL ".byte 0x0f,0x01,0xc1" 6 | #define KVM_HYPERCALL_AMD ".byte 0x0f,0x01,0xd9" 7 | 8 | static inline long kvm_hypercall0_intel(unsigned int nr) 9 | { 10 | long ret; 11 | asm volatile(KVM_HYPERCALL_INTEL 12 | : "=a"(ret) 13 | : "a"(nr)); 14 | return ret; 15 | } 16 | 17 | static inline long kvm_hypercall0_amd(unsigned int nr) 18 | { 19 | long ret; 20 | asm volatile(KVM_HYPERCALL_AMD 21 | : "=a"(ret) 22 | : "a"(nr)); 23 | return ret; 24 | } 25 | 26 | 27 | volatile unsigned long test_rip; 28 | #ifdef __x86_64__ 29 | extern void gp_tss(void); 30 | asm ("gp_tss: \n\t" 31 | "add $8, %rsp\n\t" // discard error code 32 | "popq test_rip(%rip)\n\t" // pop return address 33 | "pushq %rsi\n\t" // new return address 34 | "iretq\n\t" 35 | "jmp gp_tss\n\t" 36 | ); 37 | 38 | static inline int 39 | test_edge(void) 40 | { 41 | test_rip = 0; 42 | asm volatile ("movq $-1, %%rax\n\t" // prepare for vmcall 43 | "leaq 1f(%%rip), %%rsi\n\t" // save return address for gp_tss 44 | "movabsq $0x7ffffffffffd, %%rbx\n\t" 45 | "jmp *%%rbx; 1:" : : : "rax", "rbx", "rsi"); 46 | printf("Return from int 13, test_rip = %lx\n", test_rip); 47 | return test_rip == (1ul << 47); 48 | } 49 | #endif 50 | 51 | int main(int ac, char **av) 52 | { 53 | kvm_hypercall0_intel(-1u); 54 | printf("Hypercall via VMCALL: OK\n"); 55 | kvm_hypercall0_amd(-1u); 56 | printf("Hypercall via VMMCALL: OK\n"); 57 | 58 | #ifdef __x86_64__ 59 | setup_vm(); 60 | setup_idt(); 61 | setup_alt_stack(); 62 | set_intr_alt_stack(13, gp_tss); 63 | 64 | u8 *data1 = alloc_page(); 65 | u8 *topmost = (void *) ((1ul << 47) - PAGE_SIZE); 66 | 67 | install_pte(phys_to_virt(read_cr3()), 1, topmost, 68 | virt_to_phys(data1) | PT_PRESENT_MASK | PT_WRITABLE_MASK, 0); 69 | memset(topmost, 0xcc, PAGE_SIZE); 70 | topmost[4093] = 0x0f; 71 | topmost[4094] = 0x01; 72 | topmost[4095] = 0xc1; 73 | report("VMCALL on edge of canonical address space (intel)", test_edge()); 74 | 75 | topmost[4095] = 0xd9; 76 | report("VMMCALL on edge of canonical address space (AMD)", test_edge()); 77 | #endif 78 | 79 | return report_summary(); 80 | } 81 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/hyperv.c: -------------------------------------------------------------------------------- 1 | #include "hyperv.h" 2 | #include "asm/io.h" 3 | 4 | static void synic_ctl(u8 ctl, u8 vcpu_id, u8 sint) 5 | { 6 | outl((ctl << 16)|((vcpu_id) << 8)|sint, 0x3000); 7 | } 8 | 9 | void synic_sint_create(int vcpu, int sint, int vec, bool auto_eoi) 10 | { 11 | wrmsr(HV_X64_MSR_SINT0 + sint, 12 | (u64)vec | ((auto_eoi) ? HV_SYNIC_SINT_AUTO_EOI : 0)); 13 | synic_ctl(HV_TEST_DEV_SINT_ROUTE_CREATE, vcpu, sint); 14 | } 15 | 16 | void synic_sint_set(int vcpu, int sint) 17 | { 18 | synic_ctl(HV_TEST_DEV_SINT_ROUTE_SET_SINT, vcpu, sint); 19 | } 20 | 21 | void synic_sint_destroy(int vcpu, int sint) 22 | { 23 | wrmsr(HV_X64_MSR_SINT0 + sint, 0xFF|HV_SYNIC_SINT_MASKED); 24 | synic_ctl(HV_TEST_DEV_SINT_ROUTE_DESTROY, vcpu, sint); 25 | } 26 | -------------------------------------------------------------------------------- /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/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/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/kvm-unit-tests/x86/memory.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Test for x86 cache and memory instructions 3 | * 4 | * Copyright (c) 2015 Red Hat Inc 5 | * 6 | * Authors: 7 | * Eduardo Habkost 8 | * 9 | * This work is licensed under the terms of the GNU GPL, version 2. 10 | */ 11 | 12 | #include "libcflat.h" 13 | #include "desc.h" 14 | #include "processor.h" 15 | 16 | static long target; 17 | static volatile int ud; 18 | static volatile int isize; 19 | 20 | static void handle_ud(struct ex_regs *regs) 21 | { 22 | ud = 1; 23 | regs->rip += isize; 24 | } 25 | 26 | int main(int ac, char **av) 27 | { 28 | struct cpuid cpuid7, cpuid1; 29 | int xfail; 30 | 31 | setup_idt(); 32 | handle_exception(UD_VECTOR, handle_ud); 33 | 34 | cpuid1 = cpuid(1); 35 | cpuid7 = cpuid_indexed(7, 0); 36 | 37 | /* 3-byte instructions: */ 38 | isize = 3; 39 | 40 | xfail = !(cpuid1.d & (1U << 19)); /* CLFLUSH */ 41 | ud = 0; 42 | asm volatile("clflush (%0)" : : "b" (&target)); 43 | report_xfail("clflush", xfail, ud == 0); 44 | 45 | xfail = !(cpuid1.d & (1U << 25)); /* SSE */ 46 | ud = 0; 47 | asm volatile("sfence"); 48 | report_xfail("sfence", xfail, ud == 0); 49 | 50 | xfail = !(cpuid1.d & (1U << 26)); /* SSE2 */ 51 | ud = 0; 52 | asm volatile("lfence"); 53 | report_xfail("lfence", xfail, ud == 0); 54 | 55 | ud = 0; 56 | asm volatile("mfence"); 57 | report_xfail("mfence", xfail, ud == 0); 58 | 59 | /* 4-byte instructions: */ 60 | isize = 4; 61 | 62 | xfail = !(cpuid7.b & (1U << 23)); /* CLFLUSHOPT */ 63 | ud = 0; 64 | /* clflushopt (%rbx): */ 65 | asm volatile(".byte 0x66, 0x0f, 0xae, 0x3b" : : "b" (&target)); 66 | report_xfail("clflushopt", xfail, ud == 0); 67 | 68 | xfail = !(cpuid7.b & (1U << 24)); /* CLWB */ 69 | ud = 0; 70 | /* clwb (%rbx): */ 71 | asm volatile(".byte 0x66, 0x0f, 0xae, 0x33" : : "b" (&target)); 72 | report_xfail("clwb", xfail, ud == 0); 73 | 74 | ud = 0; 75 | /* clwb requires a memory operand, the following is NOT a valid 76 | * CLWB instruction (modrm == 0xF0). 77 | */ 78 | asm volatile(".byte 0x66, 0x0f, 0xae, 0xf0"); 79 | report("fake clwb", ud); 80 | 81 | xfail = !(cpuid7.b & (1U << 22)); /* PCOMMIT */ 82 | ud = 0; 83 | /* pcommit: */ 84 | asm volatile(".byte 0x66, 0x0f, 0xae, 0xf8"); 85 | report_xfail("pcommit", xfail, ud == 0); 86 | 87 | return report_summary(); 88 | } 89 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/port80.c: -------------------------------------------------------------------------------- 1 | #include "libcflat.h" 2 | 3 | int main() 4 | { 5 | int i; 6 | 7 | printf("begining port 0x80 write test\n"); 8 | for (i = 0; i < 10000000; ++i) 9 | asm volatile("outb %al, $0x80"); 10 | printf("done\n"); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/realmode.lds: -------------------------------------------------------------------------------- 1 | SECTIONS 2 | { 3 | . = 16K; 4 | stext = .; 5 | .text : { *(.init) *(.text) } 6 | . = ALIGN(4K); 7 | .data : { *(.data) *(.rodata*) } 8 | . = ALIGN(16); 9 | .bss : { *(.bss) } 10 | edata = .; 11 | } 12 | ENTRY(start) 13 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -z "$STANDALONE" ] && source scripts/arch-run.bash 4 | 5 | qemubinarysearch="${QEMU:-qemu-kvm qemu-system-x86_64}" 6 | 7 | for qemucmd in ${qemubinarysearch} 8 | do 9 | unset QEMUFOUND 10 | unset qemu 11 | if ! [ -z "${QEMUFOUND=$(${qemucmd} --help 2>/dev/null | grep "QEMU")}" ] && 12 | ${qemucmd} -device '?' 2>&1 | grep -F -e \"testdev\" -e \"pc-testdev\" > /dev/null; 13 | then 14 | qemu="${qemucmd}" 15 | break 16 | fi 17 | done 18 | 19 | if [ -z "${QEMUFOUND}" ] 20 | then 21 | echo "A QEMU binary was not found, You can set a custom location by using the QEMU= environment variable " 22 | exit 2 23 | elif [ -z "${qemu}" ] 24 | then 25 | echo "No Qemu test device support found" 26 | exit 2 27 | fi 28 | 29 | if 30 | ${qemu} -device '?' 2>&1 | grep -F "pci-testdev" > /dev/null; 31 | then 32 | pci_testdev="-device pci-testdev" 33 | else 34 | pci_testdev="" 35 | fi 36 | 37 | if 38 | ${qemu} -device '?' 2>&1 | grep -F "pc-testdev" > /dev/null; 39 | then 40 | pc_testdev="-device pc-testdev -device isa-debug-exit,iobase=0xf4,iosize=0x4" 41 | else 42 | pc_testdev="-device testdev,chardev=testlog -chardev file,id=testlog,path=msr.out" 43 | fi 44 | 45 | command="${qemu} -nodefaults -enable-kvm $pc_testdev -vnc none -serial stdio $pci_testdev $hyperv_testdev" 46 | [ -f "$ENV" ] && command+=" -initrd $ENV" 47 | command+=" -kernel" 48 | command="$(timeout_cmd) $command" 49 | echo ${command} "$@" 50 | 51 | run_qemu ${command} "$@" 52 | -------------------------------------------------------------------------------- /tests/kvm-unit-tests/x86/s3.c: -------------------------------------------------------------------------------- 1 | #include "libcflat.h" 2 | #include "x86/acpi.h" 3 | #include "asm/io.h" 4 | 5 | u32* find_resume_vector_addr(void) 6 | { 7 | struct facs_descriptor_rev1 *facs = find_acpi_table_addr(FACS_SIGNATURE); 8 | if (!facs) 9 | return 0; 10 | printf("FACS is at %p\n", facs); 11 | return &facs->firmware_waking_vector; 12 | } 13 | 14 | #define RTC_SECONDS_ALARM 1 15 | #define RTC_MINUTES_ALARM 3 16 | #define RTC_HOURS_ALARM 5 17 | #define RTC_ALARM_DONT_CARE 0xC0 18 | 19 | #define RTC_REG_A 10 20 | #define RTC_REG_B 11 21 | #define RTC_REG_C 12 22 | 23 | #define REG_A_UIP 0x80 24 | #define REG_B_AIE 0x20 25 | 26 | static inline int rtc_in(u8 reg) 27 | { 28 | outb(reg, 0x70); 29 | return inb(0x71); 30 | } 31 | 32 | static inline void rtc_out(u8 reg, u8 val) 33 | { 34 | outb(reg, 0x70); 35 | outb(val, 0x71); 36 | } 37 | 38 | extern char resume_start, resume_end; 39 | 40 | int main(int argc, char **argv) 41 | { 42 | struct fadt_descriptor_rev1 *fadt = find_acpi_table_addr(FACP_SIGNATURE); 43 | volatile u32 *resume_vector_ptr = find_resume_vector_addr(); 44 | char *addr, *resume_vec = (void*)0x1000; 45 | 46 | *resume_vector_ptr = (u32)(ulong)resume_vec; 47 | 48 | printf("resume vector addr is %p\n", resume_vector_ptr); 49 | for (addr = &resume_start; addr < &resume_end; addr++) 50 | *resume_vec++ = *addr; 51 | printf("copy resume code from %p\n", &resume_start); 52 | 53 | printf("PM1a event registers at %x\n", fadt->pm1a_evt_blk); 54 | outw(0x400, fadt->pm1a_evt_blk + 2); 55 | 56 | /* Setup RTC alarm to wake up on the next second. */ 57 | while ((rtc_in(RTC_REG_A) & REG_A_UIP) == 0); 58 | while ((rtc_in(RTC_REG_A) & REG_A_UIP) != 0); 59 | rtc_in(RTC_REG_C); 60 | rtc_out(RTC_SECONDS_ALARM, RTC_ALARM_DONT_CARE); 61 | rtc_out(RTC_MINUTES_ALARM, RTC_ALARM_DONT_CARE); 62 | rtc_out(RTC_HOURS_ALARM, RTC_ALARM_DONT_CARE); 63 | rtc_out(RTC_REG_B, rtc_in(RTC_REG_B) | REG_B_AIE); 64 | 65 | *(volatile int*)0 = 0; 66 | asm volatile("outw %0, %1" :: "a"((short)0x2400), "d"((short)fadt->pm1a_cnt_blk):"memory"); 67 | while(1) 68 | *(volatile int*)0 = 1; 69 | 70 | return 0; 71 | } 72 | 73 | asm ( 74 | ".global resume_start\n" 75 | ".global resume_end\n" 76 | ".code16\n" 77 | "resume_start:\n" 78 | "mov 0x0, %eax\n" 79 | "mov $0xf4, %dx\n" 80 | "out %eax, %dx\n" 81 | "1: hlt\n" 82 | "jmp 1b\n" 83 | "resume_end:\n" 84 | #ifdef __i386__ 85 | ".code32\n" 86 | #else 87 | ".code64\n" 88 | #endif 89 | ); 90 | -------------------------------------------------------------------------------- /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/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/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/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/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 %d", 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/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 | -------------------------------------------------------------------------------- /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/Makefile: -------------------------------------------------------------------------------- 1 | source_files := $(wildcard *.asm) 2 | host_executables := $(patsubst %.asm,%.bin,$(source_files)) 3 | v86_executables := $(patsubst %.asm,%.img,$(source_files)) 4 | host_fixtures := $(patsubst %.asm,%.fixture,$(source_files)) 5 | 6 | all: $(host_executables) $(v86_executables) $(host_fixtures) 7 | .PHONY: all 8 | 9 | # To run / debug locally 10 | %.bin: %.asm *.inc 11 | nasm -felf32 -o $@.o $<; ld -g $@.o -m elf_i386 -o $@ 12 | 13 | # To generate a fixture using gdb 14 | %.fixture: %.bin 15 | gdb -quiet -batch -x gdbauto $< > $@ 16 | 17 | # To use as a multiboot kernel image for v86 18 | %.img: %.asm *.inc 19 | nasm -felf32 -o $@.o $<; ld -g $@.o -m elf_i386 --section-start=.text=0x8000 -o $@ 20 | 21 | clean: 22 | rm -f *.o *.bin *.img *.fixture 23 | -------------------------------------------------------------------------------- /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 && ./run.js` in the root of the project 9 | 10 | # Manual 11 | 12 | - Run `make filename.img` to compile a multiboot kernel image to be used 13 | in v86. 14 | - Run `make filename.bin` to compile a regular ELF binary to run on 15 | a real machine. 16 | - Run `make filename.fixture` to run `filename.bin` through `gdb` with 17 | the `gdbauto` script (to extract the state of all mmx registers at 18 | the moment). 19 | -------------------------------------------------------------------------------- /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 | maskEFLAGS: 20 | dd 0x45 21 | 22 | ; Moves EFLAGS into specified register 23 | %macro moveflags 1 24 | pushf 25 | pop eax 26 | and eax, [maskEFLAGS] 27 | movd %1, eax 28 | %endmacro 29 | 30 | %include "header.inc" 31 | 32 | movd xmm0, [dword0] 33 | ; Equal 34 | comiss xmm0, [dword0] 35 | moveflags mm0 ; [ZF] = 100000 36 | ; Less than 37 | comiss xmm0, [dword1] 38 | moveflags mm1 ; [CF] = 000001 39 | ; Greater than 40 | comiss xmm0, [dword2] 41 | moveflags mm2 ; [] = 000000 42 | 43 | ; Unordered: Quiet NaN 44 | movd xmm1, [dwQNaN] 45 | ucomiss xmm0, xmm1 46 | moveflags mm3 ; [ZF][PF][CF] = 100101 47 | ; Check #I exception 48 | stmxcsr [dwordmxcsr] 49 | movd mm4, [dwordmxcsr] 50 | 51 | ; Unordered: Signaling NaN 52 | movd xmm1,[dwSNaN] 53 | ucomiss xmm0, xmm1 54 | moveflags mm5 ; [ZF][PF][CF] = 100101 55 | ; Check #I exception 56 | stmxcsr [dwordmxcsr] 57 | movd mm6, [dwordmxcsr] 58 | 59 | %include "footer.inc" 60 | -------------------------------------------------------------------------------- /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/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 ah, 0x9F 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/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/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/nasm/footer.inc: -------------------------------------------------------------------------------- 1 | loop: 2 | hlt 3 | jmp loop 4 | -------------------------------------------------------------------------------- /tests/nasm/gdbauto: -------------------------------------------------------------------------------- 1 | # Invocation: gdb -x gdbauto xyz.bin 2 | start 3 | until loop 4 | 5 | printf "---BEGIN JSON---\n" 6 | printf "[\n" 7 | printf " %d,\n", $mm0.v2_int32[0] 8 | printf " %d,\n", $mm0.v2_int32[1] 9 | printf " %d,\n", $mm1.v2_int32[0] 10 | printf " %d,\n", $mm1.v2_int32[1] 11 | printf " %d,\n", $mm2.v2_int32[0] 12 | printf " %d,\n", $mm2.v2_int32[1] 13 | printf " %d,\n", $mm3.v2_int32[0] 14 | printf " %d,\n", $mm3.v2_int32[1] 15 | printf " %d,\n", $mm4.v2_int32[0] 16 | printf " %d,\n", $mm4.v2_int32[1] 17 | printf " %d,\n", $mm5.v2_int32[0] 18 | printf " %d,\n", $mm5.v2_int32[1] 19 | printf " %d,\n", $mm6.v2_int32[0] 20 | printf " %d,\n", $mm6.v2_int32[1] 21 | printf " %d,\n", $mm7.v2_int32[0] 22 | printf " %d,\n", $mm7.v2_int32[1] 23 | printf " %d,\n", $xmm0.v4_int32[0] 24 | printf " %d,\n", $xmm0.v4_int32[1] 25 | printf " %d,\n", $xmm0.v4_int32[2] 26 | printf " %d,\n", $xmm0.v4_int32[3] 27 | printf " %d,\n", $xmm1.v4_int32[0] 28 | printf " %d,\n", $xmm1.v4_int32[1] 29 | printf " %d,\n", $xmm1.v4_int32[2] 30 | printf " %d,\n", $xmm1.v4_int32[3] 31 | printf " %d,\n", $xmm2.v4_int32[0] 32 | printf " %d,\n", $xmm2.v4_int32[1] 33 | printf " %d,\n", $xmm2.v4_int32[2] 34 | printf " %d,\n", $xmm2.v4_int32[3] 35 | printf " %d,\n", $xmm3.v4_int32[0] 36 | printf " %d,\n", $xmm3.v4_int32[1] 37 | printf " %d,\n", $xmm3.v4_int32[2] 38 | printf " %d,\n", $xmm3.v4_int32[3] 39 | printf " %d,\n", $xmm4.v4_int32[0] 40 | printf " %d,\n", $xmm4.v4_int32[1] 41 | printf " %d,\n", $xmm4.v4_int32[2] 42 | printf " %d,\n", $xmm4.v4_int32[3] 43 | printf " %d,\n", $xmm5.v4_int32[0] 44 | printf " %d,\n", $xmm5.v4_int32[1] 45 | printf " %d,\n", $xmm5.v4_int32[2] 46 | printf " %d,\n", $xmm5.v4_int32[3] 47 | printf " %d,\n", $xmm6.v4_int32[0] 48 | printf " %d,\n", $xmm6.v4_int32[1] 49 | printf " %d,\n", $xmm6.v4_int32[2] 50 | printf " %d,\n", $xmm6.v4_int32[3] 51 | printf " %d,\n", $xmm7.v4_int32[0] 52 | printf " %d,\n", $xmm7.v4_int32[1] 53 | printf " %d,\n", $xmm7.v4_int32[2] 54 | printf " %d\n", $xmm7.v4_int32[3] 55 | printf "]\n" 56 | printf "---END JSON---\n" 57 | 58 | continue 59 | quit -------------------------------------------------------------------------------- /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 .text 13 | 14 | _start: 15 | main: 16 | -------------------------------------------------------------------------------- /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/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/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/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/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/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/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/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/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/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/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/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/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 | pand mm1, [quad2] 27 | pand mm1, mm2 28 | pand mm2, [quad1] 29 | pand mm2, mm3 30 | pand mm3, [quad3] 31 | pand mm3, mm4 32 | pand mm4, [quad1] 33 | pand mm4, mm1 34 | pand mm4, mm3 35 | 36 | 37 | %include "footer.inc" 38 | -------------------------------------------------------------------------------- /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/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/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/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/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/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/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/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/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/nasm/pslld.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | myquad: 6 | dq 0xad0000ceadad00ff 7 | mydword: 8 | dd 0xcafebac0 9 | shift1: 10 | dq 0x07 11 | shift2: 12 | dq -0x22 13 | 14 | %include "header.inc" 15 | 16 | movq mm0, [myquad] 17 | movq mm1, [myquad] 18 | movq mm2, [myquad] 19 | movq mm6, [myquad] 20 | 21 | pslld mm0, [shift1] 22 | pslld mm1, 0x20 23 | pslld mm2, [shift2] 24 | pslld mm6, 0x5 25 | 26 | %include "footer.inc" 27 | -------------------------------------------------------------------------------- /tests/nasm/psllq.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | myquad: 6 | dq 0x8d0000ceadad00ff 7 | mydword: 8 | dd 0xcafebac0 9 | shift1: 10 | dq 0x07 11 | shift2: 12 | dq -0x22 13 | 14 | %include "header.inc" 15 | 16 | movq mm0, [myquad] 17 | movq mm1, [myquad] 18 | movq mm2, [myquad] 19 | movq mm3, [myquad] 20 | movq mm4, [myquad] 21 | movq mm6, [myquad] 22 | 23 | psllq mm0, [shift1] 24 | psllq mm1, [shift2] 25 | psllq mm2, 0x65 26 | psllq mm3, 0x25 27 | psllq mm4, 0x1F 28 | psllq mm6, 0x5 29 | 30 | %include "footer.inc" 31 | 32 | -------------------------------------------------------------------------------- /tests/nasm/psllw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | quad1: 6 | dq 0xad0000ceadad00ff 7 | quad2: 8 | dq 0x42ff88ff11aabbcc 9 | mydword: 10 | dd 0xcafebac0 11 | shift1: 12 | dq 0x07 13 | shift2: 14 | dq -0x22 15 | shift3: 16 | dq 8 17 | 18 | %include "header.inc" 19 | 20 | movq mm0, [quad1] 21 | movq mm1, [quad1] 22 | movq mm2, [quad1] 23 | movq mm3, [quad2] 24 | movq mm4, [quad2] 25 | movq mm6, [quad2] 26 | 27 | psllw mm0, [shift1] 28 | psllw mm1, 0xff 29 | psllw mm2, [shift2] 30 | psllw mm3, 12 31 | psllw mm4, [shift3] 32 | psllw mm6, 0x5 33 | 34 | %include "footer.inc" 35 | 36 | -------------------------------------------------------------------------------- /tests/nasm/psrad.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | myquad: 6 | dq 0xad0000ceadad00ff 7 | mydword: 8 | dd 0xcafebac0 9 | shift1: 10 | dq 0x07 11 | shift2: 12 | dq -0x22 13 | 14 | %include "header.inc" 15 | 16 | movq mm0, [myquad] 17 | movq mm1, [myquad] 18 | movq mm2, [myquad] 19 | movq mm6, [myquad] 20 | 21 | psrad mm0, [shift1] 22 | psrad mm1, 0x20 23 | psrad mm2, [shift2] 24 | psrad mm6, 0x5 25 | 26 | %include "footer.inc" 27 | -------------------------------------------------------------------------------- /tests/nasm/psraw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | myquad: 6 | dq 0xad0000ceadad00ff 7 | mydword: 8 | dd 0xcafebac0 9 | shift1: 10 | dq 0x07 11 | shift2: 12 | dq -23 13 | 14 | %include "header.inc" 15 | 16 | movq mm0, [myquad] 17 | movq mm1, [myquad] 18 | movq mm2, [myquad] 19 | movq mm6, [myquad] 20 | 21 | psraw mm0, [shift1] 22 | psraw mm1, 0xc 23 | psraw mm2, [shift2] 24 | psraw mm6, 0x5 25 | 26 | %include "footer.inc" 27 | -------------------------------------------------------------------------------- /tests/nasm/psrld.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | myquad: 6 | dq 0x8d0000ceffffadad 7 | mydword: 8 | dd 0xcafebac0 9 | shift1: 10 | dq 0x07 11 | shift2: 12 | dq -0x22 13 | 14 | %include "header.inc" 15 | 16 | movq mm0, [myquad] 17 | movq mm1, [myquad] 18 | movq mm2, [myquad] 19 | movq mm6, [myquad] 20 | 21 | psrld mm0, [shift1] 22 | psrld mm1, 0xff 23 | psrld mm2, [shift2] 24 | psrld mm6, 0x5 25 | 26 | %include "footer.inc" 27 | -------------------------------------------------------------------------------- /tests/nasm/psrlq.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | myquad: 6 | dq 0x8d0000ceadad00ff 7 | mydword: 8 | dd 0xcafebac0 9 | shift1: 10 | dq 0x07 11 | shift2: 12 | dq -0x22 13 | 14 | %include "header.inc" 15 | 16 | movq mm0, [myquad] 17 | movq mm1, [myquad] 18 | movq mm2, [myquad] 19 | movq mm3, [myquad] 20 | movq mm4, [myquad] 21 | movq mm6, [myquad] 22 | 23 | psrlq mm0, [shift1] 24 | psrlq mm1, [shift2] 25 | psrlq mm2, 0x65 26 | psrlq mm3, 0x25 27 | psrlq mm4, 0x1F 28 | psrlq mm6, 0x5 29 | 30 | %include "footer.inc" 31 | -------------------------------------------------------------------------------- /tests/nasm/psrlw.asm: -------------------------------------------------------------------------------- 1 | global _start 2 | 3 | section .data 4 | align 16 5 | myquad: 6 | dq 0xad0000ceffffadad 7 | mydword: 8 | dd 0xcafebac0 9 | shift1: 10 | dq 0x07 11 | shift2: 12 | dq -4 13 | 14 | %include "header.inc" 15 | 16 | movq mm0, [myquad] 17 | movq mm1, [myquad] 18 | movq mm2, [myquad] 19 | movq mm6, [myquad] 20 | 21 | psrlw mm0, [shift1] 22 | psrlw mm1, [mydword] 23 | psrlw mm2, [shift2] 24 | psrlw mm6, 0x5 25 | 26 | %include "footer.inc" 27 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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 | maskEFLAGS: 20 | dd 0x45 21 | 22 | ; Moves EFLAGS into specified register 23 | %macro moveflags 1 24 | pushf 25 | pop eax 26 | and eax, [maskEFLAGS] 27 | movd %1, eax 28 | %endmacro 29 | 30 | %include "header.inc" 31 | 32 | movd xmm0, [dword0] 33 | ; Equal 34 | ucomiss xmm0, [dword0] 35 | moveflags mm0 ; [ZF] = 100000 36 | ; Less than 37 | ucomiss xmm0, [dword1] 38 | moveflags mm1 ; [CF] = 000001 39 | ; Greater than 40 | ucomiss xmm0, [dword2] 41 | moveflags mm2 ; [] = 000000 42 | 43 | ; Unordered: Quiet NaN 44 | movd xmm1, [dwQNaN] 45 | ucomiss xmm0, xmm1 46 | moveflags mm3 ; [ZF][PF][CF] = 100101 47 | ; Check #I exception 48 | stmxcsr [dwordmxcsr] 49 | movd mm4, [dwordmxcsr] 50 | 51 | ; Unordered: Signaling NaN 52 | movd xmm1, [dwSNaN] 53 | ucomiss xmm0, xmm1 54 | moveflags mm5 ; [ZF][PF][CF] = 100101 55 | ; Check #I exception 56 | stmxcsr [dwordmxcsr] 57 | movd mm6, [dwordmxcsr] 58 | 59 | %include "footer.inc" 60 | -------------------------------------------------------------------------------- /tests/perf-irhydra/clean.sh: -------------------------------------------------------------------------------- 1 | rm -f code-*.asm hydrogen-*.cfg 2 | -------------------------------------------------------------------------------- /tests/perf-irhydra/run.sh: -------------------------------------------------------------------------------- 1 | # create files to analyze the emulator with irhydra. 2 | # 3 | # Important links: 4 | # http://mrale.ph/irhydra/2/ 5 | # http://mrale.ph/blog/2014/01/28/prerelease-irhydra2.html 6 | # http://mrale.ph/blog/2014/02/23/the-black-cat-of-microbenchmarks.html 7 | 8 | EMULATOR=http://localhost/v86/ 9 | 10 | chromium \ 11 | --incognito\ 12 | --no-sandbox \ 13 | --js-flags="--trace-hydrogen \ 14 | --trace-phase=Z \ 15 | --trace-deopt \ 16 | --code-comments \ 17 | --hydrogen-track-positions \ 18 | --redirect-code-traces" \ 19 | $EMULATOR 20 | 21 | 22 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /tests/qemu/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CC=gcc 3 | CC_I386=$(CC) -m32 4 | QEMU_INCLUDES += -I../.. 5 | CFLAGS=-Wall -O2 -g -fno-strict-aliasing -static -mmmx -mno-sse 6 | LDFLAGS= 7 | 8 | 9 | # i386/x86_64 emulation test (test various opcodes) */ 10 | test-i386: test-i386.c test-i386-code16.S test-i386-vm86.S \ 11 | test-i386.h test-i386-shift.h test-i386-muldiv.h 12 | $(CC_I386) $(QEMU_INCLUDES) $(CFLAGS) $(LDFLAGS) -o $@ \ 13 | $( reference` 6 | - Get the result from the VM: `./run.js > result` 7 | - The difference should be empty: `diff reference result` 8 | -------------------------------------------------------------------------------- /tests/qemu/compiler.h: -------------------------------------------------------------------------------- 1 | /* public domain */ 2 | 3 | #ifndef COMPILER_H 4 | #define COMPILER_H 5 | 6 | #include "config-host.h" 7 | 8 | /*---------------------------------------------------------------------------- 9 | | The macro QEMU_GNUC_PREREQ tests for minimum version of the GNU C compiler. 10 | | The code is a copy of SOFTFLOAT_GNUC_PREREQ, see softfloat-macros.h. 11 | *----------------------------------------------------------------------------*/ 12 | #if defined(__GNUC__) && defined(__GNUC_MINOR__) 13 | # define QEMU_GNUC_PREREQ(maj, min) \ 14 | ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) 15 | #else 16 | # define QEMU_GNUC_PREREQ(maj, min) 0 17 | #endif 18 | 19 | #define QEMU_NORETURN __attribute__ ((__noreturn__)) 20 | 21 | #if QEMU_GNUC_PREREQ(3, 4) 22 | #define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) 23 | #else 24 | #define QEMU_WARN_UNUSED_RESULT 25 | #endif 26 | 27 | #if defined(_WIN32) 28 | # define QEMU_PACKED __attribute__((gcc_struct, packed)) 29 | #else 30 | # define QEMU_PACKED __attribute__((packed)) 31 | #endif 32 | 33 | #define cat(x,y) x ## y 34 | #define cat2(x,y) cat(x,y) 35 | #define QEMU_BUILD_BUG_ON(x) \ 36 | typedef char cat2(qemu_build_bug_on__,__LINE__)[(x)?-1:1]; 37 | 38 | #if defined __GNUC__ 39 | # if !QEMU_GNUC_PREREQ(4, 4) 40 | /* gcc versions before 4.4.x don't support gnu_printf, so use printf. */ 41 | # define GCC_ATTR __attribute__((__unused__, format(printf, 1, 2))) 42 | # define GCC_FMT_ATTR(n, m) __attribute__((format(printf, n, m))) 43 | # else 44 | /* Use gnu_printf when supported (qemu uses standard format strings). */ 45 | # define GCC_ATTR __attribute__((__unused__, format(gnu_printf, 1, 2))) 46 | # define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m))) 47 | # if defined(_WIN32) 48 | /* Map __printf__ to __gnu_printf__ because we want standard format strings 49 | * even when MinGW or GLib include files use __printf__. */ 50 | # define __printf__ __gnu_printf__ 51 | # endif 52 | # endif 53 | #else 54 | #define GCC_ATTR /**/ 55 | #define GCC_FMT_ATTR(n, m) 56 | #endif 57 | 58 | #endif /* COMPILER_H */ 59 | -------------------------------------------------------------------------------- /tests/qemu/config-host.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define CONFIG_QEMU_CONFDIR "/usr/local/etc/qemu" 3 | #define CONFIG_QEMU_DATADIR "/usr/local/share/qemu" 4 | #define CONFIG_QEMU_DOCDIR "/usr/local/share/doc/qemu" 5 | #define CONFIG_QEMU_LOCALSTATEDIR "/usr/local/var" 6 | #define CONFIG_QEMU_HELPERDIR "/usr/local/libexec" 7 | #define HOST_I386 1 8 | #define CONFIG_POSIX 1 9 | #define CONFIG_LINUX 1 10 | #define CONFIG_SLIRP 1 11 | #define CONFIG_SMBD_COMMAND "/usr/sbin/smbd" 12 | #define CONFIG_AC97 1 13 | #define CONFIG_ES1370 1 14 | #define CONFIG_SB16 1 15 | #define CONFIG_HDA 1 16 | #define CONFIG_AUDIO_DRIVERS \ 17 | &oss_audio_driver,\ 18 | 19 | #define CONFIG_OSS 1 20 | #define CONFIG_BDRV_WHITELIST \ 21 | NULL 22 | #define CONFIG_VNC 1 23 | #define CONFIG_VNC_TLS 1 24 | #define CONFIG_VNC_PNG 1 25 | #define CONFIG_FNMATCH 1 26 | #define QEMU_VERSION "1.3.1" 27 | #define QEMU_PKGVERSION "" 28 | #define CONFIG_SDL 1 29 | #define CONFIG_CURSES 1 30 | #define CONFIG_ATFILE 1 31 | #define CONFIG_UTIMENSAT 1 32 | #define CONFIG_PIPE2 1 33 | #define CONFIG_ACCEPT4 1 34 | #define CONFIG_SPLICE 1 35 | #define CONFIG_EVENTFD 1 36 | #define CONFIG_FALLOCATE 1 37 | #define CONFIG_SYNC_FILE_RANGE 1 38 | #define CONFIG_FIEMAP 1 39 | #define CONFIG_DUP3 1 40 | #define CONFIG_EPOLL 1 41 | #define CONFIG_EPOLL_CREATE1 1 42 | #define CONFIG_EPOLL_PWAIT 1 43 | #define CONFIG_INOTIFY 1 44 | #define CONFIG_INOTIFY1 1 45 | #define CONFIG_BYTESWAP_H 1 46 | #define CONFIG_CURL 1 47 | #define CONFIG_ATTR 1 48 | #define CONFIG_IOVEC 1 49 | #define CONFIG_PREADV 1 50 | #define CONFIG_SIGNALFD 1 51 | #define CONFIG_FDATASYNC 1 52 | #define CONFIG_MADVISE 1 53 | #define CONFIG_POSIX_MADVISE 1 54 | #define CONFIG_SIGEV_THREAD_ID 1 55 | #define CONFIG_SMARTCARD 1 56 | #define CONFIG_OPENGL 1 57 | #define CONFIG_UNAME_RELEASE "" 58 | #define CONFIG_ZERO_MALLOC 1 59 | #define CONFIG_UCONTEXT_COROUTINE 1 60 | #define CONFIG_OPEN_BY_HANDLE 1 61 | #define CONFIG_LINUX_MAGIC_H 1 62 | #define CONFIG_PRAGMA_DISABLE_UNUSED_BUT_SET 1 63 | #define CONFIG_HAS_ENVIRON 1 64 | #define CONFIG_TRACE_NOP 1 65 | #define CONFIG_TRACE_FILE trace 66 | #define CONFIG_TRACE_DEFAULT 1 67 | -------------------------------------------------------------------------------- /tests/qemu/run.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | var V86 = require("../../build/libv86.js").V86; 5 | var fs = require("fs"); 6 | 7 | var test_executable = new Uint8Array(fs.readFileSync(__dirname + "/test-i386")); 8 | 9 | var emulator = new V86({ 10 | bios: { url: __dirname + "/../../bios/seabios.bin" }, 11 | vga_bios: { url: __dirname + "/../../bios/vgabios.bin" }, 12 | cdrom: { url: __dirname + "/../../images/linux3.iso" }, 13 | autostart: true, 14 | memory_size: 32 * 1024 * 1024, 15 | filesystem: {}, 16 | }); 17 | 18 | emulator.bus.register("emulator-started", function() 19 | { 20 | console.error("Booting now, please stand by"); 21 | emulator.create_file("test-i386", test_executable); 22 | }); 23 | 24 | var ran_command = false; 25 | var line = ""; 26 | 27 | emulator.add_listener("serial0-output-char", function(chr) 28 | { 29 | if(chr < " " && chr !== "\n" && chr !== "\t" || chr > "~") 30 | { 31 | return; 32 | } 33 | 34 | if(chr === "\n") 35 | { 36 | var new_line = line; 37 | console.error("Serial: %s", line); 38 | line = ""; 39 | } 40 | else 41 | { 42 | line += chr; 43 | } 44 | 45 | if(!ran_command && line.endsWith("~% ")) 46 | { 47 | ran_command = true; 48 | emulator.serial0_send("chmod +x /mnt/test-i386\n"); 49 | emulator.serial0_send("/mnt/test-i386 > /mnt/result\n"); 50 | emulator.serial0_send("echo test fini''shed\n"); 51 | } 52 | 53 | if(new_line && new_line.includes("test finished")) 54 | { 55 | console.error("Done. Reading result ..."); 56 | 57 | emulator.read_file("/result", function(err, data) 58 | { 59 | if(err) throw err; 60 | console.error("Got result, writing to stdout"); 61 | process.stdout.write(new Buffer(data)); 62 | emulator.stop(); 63 | }); 64 | } 65 | 66 | }); 67 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /tests/qemu/test-i386-muldiv.h: -------------------------------------------------------------------------------- 1 | 2 | void glue(glue(test_, OP), b)(long op0, long op1) 3 | { 4 | long res, s1, s0, flags; 5 | s0 = op0; 6 | s1 = op1; 7 | res = s0; 8 | flags = 0; 9 | asm ("push %4\n\t" 10 | "popf\n\t" 11 | stringify(OP)"b %b2\n\t" 12 | "pushf\n\t" 13 | "pop %1\n\t" 14 | : "=a" (res), "=g" (flags) 15 | : "q" (s1), "0" (res), "1" (flags)); 16 | printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n", 17 | stringify(OP) "b", s0, s1, res, flags & CC_MASK); 18 | } 19 | 20 | void glue(glue(test_, OP), w)(long op0h, long op0, long op1) 21 | { 22 | long res, s1, flags, resh; 23 | s1 = op1; 24 | resh = op0h; 25 | res = op0; 26 | flags = 0; 27 | asm ("push %5\n\t" 28 | "popf\n\t" 29 | stringify(OP) "w %w3\n\t" 30 | "pushf\n\t" 31 | "pop %1\n\t" 32 | : "=a" (res), "=g" (flags), "=d" (resh) 33 | : "q" (s1), "0" (res), "1" (flags), "2" (resh)); 34 | printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n", 35 | stringify(OP) "w", op0h, op0, s1, resh, res, flags & CC_MASK); 36 | } 37 | 38 | void glue(glue(test_, OP), l)(long op0h, long op0, long op1) 39 | { 40 | long res, s1, flags, resh; 41 | s1 = op1; 42 | resh = op0h; 43 | res = op0; 44 | flags = 0; 45 | asm ("push %5\n\t" 46 | "popf\n\t" 47 | stringify(OP) "l %k3\n\t" 48 | "pushf\n\t" 49 | "pop %1\n\t" 50 | : "=a" (res), "=g" (flags), "=d" (resh) 51 | : "q" (s1), "0" (res), "1" (flags), "2" (resh)); 52 | printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n", 53 | stringify(OP) "l", op0h, op0, s1, resh, res, flags & CC_MASK); 54 | } 55 | 56 | #if defined(__x86_64__) 57 | void glue(glue(test_, OP), q)(long op0h, long op0, long op1) 58 | { 59 | long res, s1, flags, resh; 60 | s1 = op1; 61 | resh = op0h; 62 | res = op0; 63 | flags = 0; 64 | asm ("push %5\n\t" 65 | "popf\n\t" 66 | stringify(OP) "q %3\n\t" 67 | "pushf\n\t" 68 | "pop %1\n\t" 69 | : "=a" (res), "=g" (flags), "=d" (resh) 70 | : "q" (s1), "0" (res), "1" (flags), "2" (resh)); 71 | printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n", 72 | stringify(OP) "q", op0h, op0, s1, resh, res, flags & CC_MASK); 73 | } 74 | #endif 75 | 76 | #undef OP 77 | -------------------------------------------------------------------------------- /tests/qemu/test-i386-vm86.S: -------------------------------------------------------------------------------- 1 | .code16 2 | .globl vm86_code_start 3 | .globl vm86_code_end 4 | 5 | #define GET_OFFSET(x) ((x) - vm86_code_start + 0x100) 6 | 7 | vm86_code_start: 8 | movw $GET_OFFSET(hello_world), %dx 9 | movb $0x09, %ah 10 | int $0x21 11 | 12 | /* prepare int 0x90 vector */ 13 | xorw %ax, %ax 14 | movw %ax, %es 15 | es movw $GET_OFFSET(int90_test), 0x90 * 4 16 | es movw %cs, 0x90 * 4 + 2 17 | 18 | /* launch int 0x90 */ 19 | 20 | int $0x90 21 | 22 | /* test IF support */ 23 | movw $GET_OFFSET(IF_msg), %dx 24 | movb $0x09, %ah 25 | int $0x21 26 | 27 | pushf 28 | popw %dx 29 | movb $0xff, %ah 30 | int $0x21 31 | 32 | cli 33 | pushf 34 | popw %dx 35 | movb $0xff, %ah 36 | int $0x21 37 | 38 | sti 39 | pushfl 40 | popl %edx 41 | movb $0xff, %ah 42 | int $0x21 43 | 44 | #if 0 45 | movw $GET_OFFSET(IF_msg1), %dx 46 | movb $0x09, %ah 47 | int $0x21 48 | 49 | pushf 50 | movw %sp, %bx 51 | andw $~0x200, (%bx) 52 | popf 53 | #else 54 | cli 55 | #endif 56 | 57 | pushf 58 | popw %dx 59 | movb $0xff, %ah 60 | int $0x21 61 | 62 | pushfl 63 | movw %sp, %bx 64 | orw $0x200, (%bx) 65 | popfl 66 | 67 | pushfl 68 | popl %edx 69 | movb $0xff, %ah 70 | int $0x21 71 | 72 | movb $0x00, %ah 73 | int $0x21 74 | 75 | int90_test: 76 | pushf 77 | pop %dx 78 | movb $0xff, %ah 79 | int $0x21 80 | 81 | movw %sp, %bx 82 | movw 4(%bx), %dx 83 | movb $0xff, %ah 84 | int $0x21 85 | 86 | movw $GET_OFFSET(int90_msg), %dx 87 | movb $0x09, %ah 88 | int $0x21 89 | iret 90 | 91 | int90_msg: 92 | .string "INT90 started\n$" 93 | 94 | hello_world: 95 | .string "Hello VM86 world\n$" 96 | 97 | IF_msg: 98 | .string "VM86 IF test\n$" 99 | 100 | IF_msg1: 101 | .string "If you see a diff here, your Linux kernel is buggy, please update to 2.4.20 kernel\n$" 102 | 103 | vm86_code_end: 104 | --------------------------------------------------------------------------------