├── .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 |
2 |
3 | function anchorify(str)
4 | {
5 | // how github creates the name attribute for anchors from headlines
6 |
7 | str = str.replace(/[()<>.]/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 | ?>= "- [`" + comment.longName + "`](#" + anchorify(comment.longName) + ")\n" ?>
48 | } else {
49 | ?># = comment.name + "\n" ?>
50 | }
51 | }
52 | });
53 |
54 | doc.javadoc.forEach(function(comment)
55 | {
56 | if(!comment.ignore)
57 | {
58 | ?>= "\n***\n" ?>
59 |
60 | if(comment.name)
61 | {
62 | if(comment.isMethod || comment.isFunction)
63 | {
64 | ?>= "#### `" + comment.longName + "`\n" ?>
65 | }
66 | else
67 | {
68 | ?>= "## `" + comment.name + "`\n" ?>
69 | }
70 | }
71 |
72 | if(comment.deprecated)
73 | {
74 | ?>= "\n\n**Deprecated - Might be removed in a later release.**\n\n" ?>
75 | }
76 |
77 | ?>= comment.description + "\n" ?>
78 |
79 |
80 | if(comment.paramTags.length)
81 | {
82 | ?>= "**Parameters:**\n\n" ?>
83 |
84 | comment.paramTags.forEach(function(paramTag, i)
85 | {
86 | ?>= (i + 1) + ". **`" + paramTag.joinedTypes + "`** " + (paramTag.optional ? "(optional) " : "") + paramTag.name + " " + (paramTag.description ? "– " + paramTag.description : "") + "\n" ?>
87 | });
88 | }
89 |
90 | if(comment.returnTags.length)
91 | {
92 | ?>= "**Returns:**\n\n" ?>
93 |
94 | comment.returnTags.forEach(function(returnTag)
95 | {
96 | ?>= "* **`" + returnTag.joinedTypes + "`** " + returnTag.description + "\n" ?>
97 | });
98 | }
99 | }
100 | });
101 |
102 | ?>= "\n\n" ?>
103 | });
104 |
105 | ?>
106 |
107 |
108 |
--------------------------------------------------------------------------------
/examples/arch.html:
--------------------------------------------------------------------------------
1 |
2 | Archlinux
3 |
4 |
5 |
73 |
74 |
75 | Restore from file:
76 |
77 |
78 |
79 |
83 |
--------------------------------------------------------------------------------
/examples/async_load.html:
--------------------------------------------------------------------------------
1 |
2 | Asynchronous loading of disk images
3 |
4 |
5 |
38 |
39 |
43 |
--------------------------------------------------------------------------------
/examples/basic.html:
--------------------------------------------------------------------------------
1 |
2 | Basic Emulator
3 |
4 |
5 |
27 |
28 |
29 |
33 |
--------------------------------------------------------------------------------
/examples/destroy.html:
--------------------------------------------------------------------------------
1 |
2 | Destroyable Emulator
3 |
4 |
5 |
29 |
30 |
34 |
--------------------------------------------------------------------------------
/examples/lang.html:
--------------------------------------------------------------------------------
1 |
2 | Basic Emulator
3 |
4 |
5 |
79 |
80 |
81 |
82 |
83 |
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 |
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 |
109 |
--------------------------------------------------------------------------------
/examples/serial.html:
--------------------------------------------------------------------------------
1 |
2 | Serial example
3 |
4 |
5 |
76 |
77 |
79 |
80 |
81 |
82 |
86 |
--------------------------------------------------------------------------------
/examples/two_instances.html:
--------------------------------------------------------------------------------
1 |
2 | Two emulators
3 |
4 |
5 |
67 |
68 | Click on a screen to control it.
69 |
70 |
74 |
75 |
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 |
--------------------------------------------------------------------------------