Materials for Advanced x86
Course
- lesson 1 : Architectural changes overview
- lesson 2 : Firmware, Boot & Devices
- lesson 3 : Virtualization
- lesson 4 : Device Virtualization
old lessons :
- lesson 1 : Architectural changes overview
- lesson 2 : Firmware, Boot & Devices
- lesson 3 : Multi-Core
- lesson 4 : Virtualization
- lesson 5 : Qemu/KVM
Bibliography and References
- Intel Manual : Intel® 64 and IA-32 Architectures Software Developer Manuals
- TLS explanation : Ulrich Drepper, ELF Handling For Thread-Local Storage
- x86_64 ABI : System V Application Binary Interface - x86-64 Linux
- Calling Conventions : What are the calling conventions for UNIX & Linux system calls on x86-64
- Virtual Memory Explanation : What Every Programmer Should Know About Memory
- PAX implementation : Page Exec
- Linux Boot Protocol : Documentation/x86/boot.txt
- x86 Firmware initialization : Part 1 Part 2
- MultiProcessor Specification : Specification
- ACPI Specification : Specification
- Virtio Specification : Specification
- Shared Libraries : Ulrich Drepper, How To Write Shared Libraries
Assignments
The git repository used for the assignments are on git-stos.lse.epita.fr
Exercises for the Tue May 19
Every exercises must have a Makefile, and the source code. It should contains tests.
Exercise 1 : string
Assignment : Implement a dynamic library with string functions in x86_64 assembly.
Your library should be usable with the following header :
#ifndef STRING_H
#define STRING_H
#include <stddef.h>
size_t strlen(const char *s);
char *strcpy(char *dest, const char *src);
void *memcpy(void *dest, const void *src, size_t n);
#endif
You should produce a library named libstring.so
Exercise 2 : cat
Assignment : Implement a cat
binary in x86_64 assembly.
- You binary must be PIE
- without any external dependancies
- you can still use the linux headers
- you must use the
syscall
instruction for syscalls.
Example :
$ gcc -shared -nostartfiles -fno-builtin -nostdlib -o cat cat.S
$ IFS=:
$ for i in $PATH ; do sudo rm $i/cat ; done
$ echo foo > foo
$ ./cat foo
foo
$ echo foo | ./cat
foo
$ rm -f bar
$ ./cat bar
cat: Error
$
Exercise 3 : mptables
Assignment : Implement a stos kernel module that dumps the content of the mptables
- This is a test module
- It will output the content of the mptables with klog()
Project : MyKVM
Usage :
mykvm -f stos.boot
mykvm --help
mykvm -m 128 --kernel kernel/stos \
--initrd initramfs.img \
--modules module.ko,module2.ko \
init.mode=all
other modes must be described in --help
Assignment : Create a small vm tool with kvm. The goal is to be able to boot stos.
stos.boot
is a simple .ini
file that looks like this (you will probably
have to change the paths to match have something that make sense on your
machine):
commandline=init.mode=all
kernel=/kernel/stos
initramfs=/kernel/initramfs.img
module=/kernel/modules/8259A.ko
module=/kernel/modules/cpuvar.ko
module=/kernel/modules/i8042.ko
module=/kernel/modules/i8254.ko
module=/kernel/modules/ide.ko
module=/kernel/modules/interrupts.ko
module=/kernel/modules/isa-serial.ko
module=/kernel/modules/pagination.ko
module=/kernel/modules/pci.ko
module=/kernel/modules/pm.ko
module=/kernel/modules/zero.ko
module=/kernel/modules/null.ko
module=/kernel/modules/kmsg.ko
module=/kernel/modules/16550.ko
module=/kernel/modules/pci-serial.ko
module=/kernel/modules/devfs.ko
module=/kernel/modules/ext2.ko
module=/kernel/modules/mbr_part_table.ko
module=/kernel/modules/mbrfs.ko
module=/kernel/modules/ramfs.ko
module=/kernel/modules/vfs.ko
module=/kernel/modules/bin_elf.ko
module=/kernel/modules/block.ko
module=/kernel/modules/char.ko
module=/kernel/modules/commandline.ko
module=/kernel/modules/fifo_io_sched.ko
module=/kernel/modules/fifo_scheduler.ko
module=/kernel/modules/first_fit_kmalloc.ko
module=/kernel/modules/frame_allocator.ko
module=/kernel/modules/libraries.ko
module=/kernel/modules/posix.ko
module=/kernel/modules/start_uland.ko
module=/kernel/modules/test.ko
module=/kernel/modules/syscall.ko
module=/kernel/modules/syslog.ko
module=/kernel/modules/task.ko
module=/kernel/modules/init.ko
Steps :
- Create basic VM
- Boot some code directly in PM mode
- Add serial handling
- add pagination like in
stos.grub
- start to handle stos boot protocol
- start building from that :
- module support
- memory map support
- commandline support
- initramfs support
- more devices
Please note that the absolute minimum is to be able to boot the stos core, with commandline support, complete memory mapping.
Module and initramfs support are the 2nd step.
For debugging support, and to be able to see if the code behave correctly in qemu and in your code, you can implement a subset of the multiboot spec with :
- 32bit
- multiboot
- serial
More explanation (in French)
Voici quelques précisions sur le sujet et la marche à suivre (une update du site arrivera aussi, plus tard, histoire de refléter ces changements)
- Donnez moi un README m’expliquant comment faire marcher votre projet exactement, avec les fichiers de conf, comment compiler la version de stos que vous avez utilisé, etc…
- Il est a noter que je retirerai des points à tout ceux qui incluent directement stos dans leur dépots. Je préfère voir un script/submodule/whatever plutôt que ça (à préciser dans le README)
- La partie obligatoire (comprendre, pour avoir 10 si ca marche) est :
- chargement du core
- pagination
- gestion du protocole de boot de stos
- commandline
- serial en output
- Les étapes suivantes sont :
- modules
- initramfs
- En bonus potentiels :
- tests pour valider le tout (dans stos, ou en userland)
- gestion complète du serial (input, output, irq)
- vga text
- supprimer ioctl(
CREATE_IRQCHIP
)
-
le multiboot est ici indiqué pour vous aider à debugger plus facilement, vu que vous pourrez lancer des exemples qui tournerons dans qemu et dans votre vm. Cela ne vaut aucun points si vous n’avez pas la partie mandatory.
-
Faites attention aux headers de stos, ils sont valide uniquement en 32bit, comme votre binaire sera 64bit, il faut patcher les structures pour être aligné correctement (Attention à la règle de padding de gcc sur les valeurs 64bit).
-
Il y a une erreur dans les slides par rapport à l’ioctl
KVM_SET_IDENTITY_MAP_ADDR
. En effet, la définition de l’ioctl est :#define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64) et non #define KVM_SET_IDENTITY_MAP_ADDR _IO(KVMIO, 0x48) je vous laisse en déduire ce qu’il fallait marquer.
- Pour la pagination, il y a un petit détail que je ne vous ai pas
précisé. KVM ne sait pas démarrer directement avec
%cr0.PG = 1
, il faut donc faire un trampoline pour activer la pagination avant de lancer stos.