├── .bochsrc ├── LICENSE ├── Makefile ├── README.md ├── buildhddimg ├── LICENSE └── buildhddimg.sh ├── linker.ld ├── loader.S ├── movdbz-addition.s ├── movdbz-as.py ├── run_movdbz_program.c ├── screen.c ├── screen.h ├── set_gdtr.S ├── setup.c └── setup.h /.bochsrc: -------------------------------------------------------------------------------- 1 | # configuration file generated by Bochs 2 | plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, gameport=1, pci_ide=1, acpi=1, ioapic=1 3 | config_interface: textconfig 4 | display_library: sdl 5 | memory: host=2048, guest=2048 6 | romimage: file="/usr/share/bochs/BIOS-bochs-latest" 7 | vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest" 8 | boot: disk 9 | floppy_bootsig_check: disabled=0 10 | # no floppya 11 | # no floppyb 12 | ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 13 | ata0-master: type=disk, mode=flat, translation=auto, path="harddisk.img", biosdetect=auto, model="Generic 1234" 14 | ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 15 | ata2: enabled=0 16 | ata3: enabled=0 17 | parport1: enabled=1, file="" 18 | parport2: enabled=0 19 | com1: enabled=1, mode=null, dev="" 20 | com2: enabled=0 21 | com3: enabled=0 22 | com4: enabled=0 23 | usb_uhci: enabled=0 24 | usb_ohci: enabled=0 25 | i440fxsupport: enabled=1 26 | vga_update_interval: 50000 27 | vga: extension=vbe 28 | cpu: count=1, ips=4000000, reset_on_triple_fault=1, ignore_bad_msrs=1 29 | cpuid: cpuid_limit_winnt=0, mmx=1, sse=sse2, xapic=1, sep=1, aes=0, xsave=0, movbe=0, 1g_pages=0, pcid=0 fsgsbase=0 30 | cpuid: stepping=3, vendor_string="GenuineIntel", brand_string=" Intel(R) Pentium(R) 4 CPU " 31 | print_timestamps: enabled=0 32 | # no gdb stub 33 | port_e9_hack: enabled=0 34 | text_snapshot_check: enabled=0 35 | private_colormap: enabled=0 36 | clock: sync=none, time0=local 37 | # no cmosimage 38 | ne2k: enabled=0 39 | pnic: enabled=0 40 | sb16: enabled=0 41 | # no loader 42 | log: - 43 | logprefix: %t%e%d 44 | panic: action=ask 45 | error: action=report 46 | info: action=report 47 | debug: action=ignore 48 | pass: action=fatal 49 | keyboard_type: mf 50 | keyboard_serial_delay: 250 51 | keyboard_paste_delay: 100000 52 | keyboard_mapping: enabled=0, map= 53 | user_shortcut: keys=none 54 | mouse: enabled=0, type=ps2, toggle=ctrl+mbutton 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Krister Walfridsson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | MOVDBZ_PROG=movdbz-addition.s 2 | 3 | CPPFLAGS=-m32 -std=c99 -ffreestanding 4 | CFLAGS=-Wall -Wextra -nostdlib -O2 5 | 6 | objects = loader.o run_movdbz_program.o screen.o set_gdtr.o setup.o 7 | 8 | harddisk.img: buildhddimg/buildhddimg.sh kernel.bin 9 | buildhddimg/buildhddimg.sh 10 | 11 | kernel.bin: $(objects) linker.ld 12 | ld -T linker.ld -m elf_i386 -o $@ $(objects) 13 | 14 | generated-prog.c: movdbz-as.py $(MOVDBZ_PROG) 15 | ./movdbz-as.py -o generated-prog.c $(MOVDBZ_PROG) 16 | 17 | loader.o: loader.S 18 | run_movdbz_program.o: run_movdbz_program.c screen.h setup.h 19 | screen.o: screen.c screen.h 20 | set_gdtr.o: set_gdtr.S 21 | setup.o: generated-prog.c screen.h setup.c setup.h 22 | 23 | .PHONY : clean 24 | clean: 25 | rm -f *.o *.bin *.img *.log generated-prog.c 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Instruction-less computation 2 | This is an implementation of the ideas in the paper “[The Page-Fault Weird Machine: Lessons in Instruction-less Computation](https://www.usenix.org/conference/woot13/workshop-program/presentation/bangert)” by J. Bangert et al., where it is shown that the IA-32 fault handling mechanism is Turing complete, so you can run programs without executing any CPU instructions! 3 | 4 | I did this implementation to get an understanding of how it works in detail – the paper does not describe all the boring parts needed to get this working, and the [trapcc](https://github.com/jbangert/trapcc) implementation from the paper is IMHO hard to understand (it generates all the page tables etc. by Ruby scripts, and it needs to do global analysis with graph coloring etc. to generate working programs). My implementation tries to be easier to understand by choosing a less efficient instruction encoding that eliminates the need of global analysis, so each instruction can be generated individually. 5 | 6 | I have made a Python assembler that generates some code, but that is only syntactic sugar that is not strictly needed. For example, instructions 7 | 8 | ``` 9 | L5: movdbz r3, 1024, L7, L7 10 | L7: movdbz r2, r2, L8, exit 11 | L8: movdbz r3, r3, L7, L7 12 | ``` 13 | 14 | are generated as the C code 15 | 16 | ``` 17 | gen_movdbz(5, 3, 4, 6, 6); // L5: movdbz r3, 1024, L7, L7 18 | gen_movdbz(6, 2, 2, 7, -1); // L7: movdbz r2, r2, L8, exit 19 | gen_movdbz(7, 3, 3, 6, 6); // L8: movdbz r3, r3, L7, L7 20 | ``` 21 | 22 | and it should be easy to follow how each instruction is generated as page tables etc. The construction is described in two blog posts ([overview](http://kristerw.blogspot.se/2015/08/instruction-less-computation.html) and [technical details](http://kristerw.blogspot.se/2015/08/instruction-less-computation-technical.html)). 23 | 24 | ### Building and running the software 25 | Building the software is as easy as to run 26 | ``` 27 | make 28 | ``` 29 | which builds a kernel that you need to run on the bochs emulator (or real hardware). It may be possible to use other emulators, but the paper claims that none implements the correct fault behaviour (but that may have been fixed since the paper was written...). 30 | 31 | I tested to build on a clean Ubuntu 14.04.3 LTS 64-bit desktop, and you only need to install `bochs-sdl` to be ready to go. 32 | 33 | There is a bochs configuration file in the repository, so running bochs in the source code directory should use it autimatically. 34 | 35 | ### Changing the movdbz program 36 | The example movdbz program in this repository can be found in [movdbz-addition.s](movdbz-addition.s), and it implements addition as described in the [blog post](http://kristerw.blogspot.se/2015/08/instruction-less-computation.html). You can change this to your own file by updating the `MOVDBZ_PROG` variable in the [Makefile](Makefile), and updating [run_movdbz_program.c](run_movdbz_program.c) to set up the input/output for your program. 37 | 38 | ### Assembler syntax 39 | The constructed machine is a "one instruction set computer", so the assembler has only one instruction: `movdbz`. 40 | 41 | The format of the assembler is 42 | ``` 43 |