{"id":18470302,"url":"https://github.com/dreadl0ck/microbench","last_synced_at":"2025-05-12T03:09:22.278Z","repository":{"id":195650425,"uuid":"223115799","full_name":"dreadl0ck/microbench","owner":"dreadl0ck","description":"MICROBENCH - A testbed for comparing microvm technologies","archived":false,"fork":false,"pushed_at":"2020-11-12T16:51:07.000Z","size":16358,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-05-09T00:12:18.319Z","etag":null,"topics":["firecracker","microvm","qemu","virtualization"],"latest_commit_sha":null,"homepage":"","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dreadl0ck.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-11-21T07:38:33.000Z","updated_at":"2025-01-01T10:14:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"eac6a22c-fef3-4e9d-b7d6-a597d9bcd0db","html_url":"https://github.com/dreadl0ck/microbench","commit_stats":null,"previous_names":["dreadl0ck/microbench"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dreadl0ck%2Fmicrobench","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dreadl0ck%2Fmicrobench/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dreadl0ck%2Fmicrobench/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dreadl0ck%2Fmicrobench/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dreadl0ck","download_url":"https://codeload.github.com/dreadl0ck/microbench/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253166524,"owners_count":21864482,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["firecracker","microvm","qemu","virtualization"],"created_at":"2024-11-06T10:13:33.206Z","updated_at":"2025-05-09T00:12:25.782Z","avatar_url":"https://github.com/dreadl0ck.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"# README\n\n## Firecracker Setup\n\n### check for hardware virtualization support\n\n    egrep -c '(vmx|svm)' /proc/cpuinfo\n\n\u003e must be \u003e 0\n\n### install KVM and docker\n\n    # apt install qemu-kvm libvirt-bin bridge-utils\n    # apt install vim tree curl docker.io make gcc\n\nfetch kernel and rootfs:\n\n    wget https://s3.amazonaws.com/spec.ccfc.min/img/hello/kernel/hello-vmlinux.bin\n    wget https://s3.amazonaws.com/spec.ccfc.min/img/hello/fsfiles/hello-rootfs.ext4\n\nbuild firecracker from source:\n\n    git clone https://github.com/firecracker-microvm/firecracker\n    cd firecracker\n    tools/devtool build\n    toolchain=\"$(uname -m)-unknown-linux-musl\"\n\nrun:\n\n    cd firecracker \u0026\u0026 \\\n    toolchain=\"$(uname -m)-unknown-linux-musl\" \u0026\u0026 \\\n    rm -f /tmp/firecracker.socket \u0026\u0026 \\\n    build/cargo_target/${toolchain}/debug/firecracker --api-sock /tmp/firecracker.socket\n\nIn your **second shell** prompt:\n\n- get the kernel and rootfs, if you don't have any available:\n\n  ```bash\n    arch=`uname -m`\n    dest_kernel=\"hello-vmlinux.bin\"\n    dest_rootfs=\"hello-rootfs.ext4\"\n    image_bucket_url=\"https://s3.amazonaws.com/spec.ccfc.min/img\"\n\n    if [ ${arch} = \"x86_64\" ]; then\n            kernel=\"${image_bucket_url}/hello/kernel/hello-vmlinux.bin\"\n            rootfs=\"${image_bucket_url}/hello/fsfiles/hello-rootfs.ext4\"\n    elif [ ${arch} = \"aarch64\" ]; then\n            kernel=\"${image_bucket_url}/aarch64/ubuntu_with_ssh/kernel/vmlinux.bin\"\n            rootfs=\"${image_bucket_url}/aarch64/ubuntu_with_ssh/fsfiles/xenial.rootfs.ext4\"\n    else\n            echo \"Cannot run firecracker on $arch architecture!\"\n            exit 1\n    fi\n\n    echo \"Downloading $kernel...\"\n    curl -fsSL -o $dest_kernel $kernel\n\n    echo \"Downloading $rootfs...\"\n    curl -fsSL -o $dest_rootfs $rootfs\n\n    echo \"Saved kernel file to $dest_kernel and root block device to $dest_rootfs.\"\n  ```\n\n- set the guest kernel:\n\n  ```bash\n    arch=`uname -m`\n    kernel_path=\"$(readlink -f hello-vmlinux.bin)\"\n    file $kernel_path\n\n    if [ ${arch} = \"x86_64\" ]; then\n      curl --unix-socket /tmp/firecracker.socket -i \\\n          -X PUT 'http://localhost/boot-source'   \\\n          -H 'Accept: application/json'           \\\n          -H 'Content-Type: application/json'     \\\n          -d \"{\n                \\\"kernel_image_path\\\": \\\"${kernel_path}\\\",\n                \\\"boot_args\\\": \\\"console=ttyS0 reboot=k panic=1 pci=off\\\"\n           }\"\n    elif [ ${arch} = \"aarch64\" ]; then\n        curl --unix-socket /tmp/firecracker.socket -i \\\n          -X PUT 'http://localhost/boot-source'   \\\n          -H 'Accept: application/json'           \\\n          -H 'Content-Type: application/json'     \\\n          -d \"{\n                \\\"kernel_image_path\\\": \\\"${kernel_path}\\\",\n                \\\"boot_args\\\": \\\"keep_bootcon console=ttyS0 reboot=k panic=1 pci=off\\\"\n           }\"\n    else\n        echo \"Cannot run firecracker on $arch architecture!\"\n        exit 1\n    fi\n  ```\n\n- set the guest rootfs:\n\n  ```bash\n    rootfs_path=\"$(readlink -f hello-rootfs.ext4)\"\n    file $rootfs_path\n\n    curl --unix-socket /tmp/firecracker.socket -i \\\n      -X PUT 'http://localhost/drives/rootfs' \\\n      -H 'Accept: application/json'           \\\n      -H 'Content-Type: application/json'     \\\n      -d \"{\n            \\\"drive_id\\\": \\\"rootfs\\\",\n            \\\"path_on_host\\\": \\\"${rootfs_path}\\\",\n            \\\"is_root_device\\\": true,\n            \\\"is_read_only\\\": false\n       }\"\n  ```\n\n- start the guest machine:\n\n  ```bash\n  curl --unix-socket /tmp/firecracker.socket -i \\\n      -X PUT 'http://localhost/actions'       \\\n      -H  'Accept: application/json'          \\\n      -H  'Content-Type: application/json'    \\\n      -d '{\n          \"action_type\": \"InstanceStart\"\n       }'\n  ```\n\n```bash\n  curl --unix-socket /tmp/firecracker.socket -i \\\n      -X PUT 'http://localhost/actions'       \\\n      -H  'Accept: application/json'          \\\n      -H  'Content-Type: application/json'    \\\n      -d '{\n          \"action_type\": \"SendCtrlAltDel\"\n       }'\n  ```\n\nGoing back to your first shell, you should now see a serial TTY prompting you\nto log into the guest machine. If you used our `hello-rootfs.ext4` image,\nyou can login as `root`, using the password `root`.\n\nWhen you're done, issuing a `reboot` command inside the guest will actually\nshutdown Firecracker gracefully. This is due to the fact that Firecracker\ndoesn't implement guest power management.\n\n### VM Configuration via API\n\n**Note**: the default microVM will have 1 vCPU and 128 MiB RAM. If you wish to\ncustomize that (say, 2 vCPUs and 1024MiB RAM), you can do so before issuing\nthe `InstanceStart` call, via this API command:\n\n```bash\ncurl --unix-socket /tmp/firecracker.socket -i  \\\n    -X PUT 'http://localhost/machine-config' \\\n    -H 'Accept: application/json'            \\\n    -H 'Content-Type: application/json'      \\\n    -d '{\n        \"vcpu_count\": 2,\n        \"mem_size_mib\": 1024,\n        \"ht_enabled\": false\n    }'\n```\n\n#### Configuring the microVM without sending API requests\n\nIf you'd like to boot up a guest machine without using the API socket, you can do that \nby passing the parameter `--config-file` to the Firecracker process. The command for \nstarting Firecracker with this option will look like this:\n\n```bash\n./firecracker --api-sock /tmp/firecracker.socket --config-file \n\u003cpath_to_the_configuration_file\u003e\n```\n\n`path_to_the_configuration_file` should represent the path to a file that contains a \nJSON which stores the entire configuration for all of the microVM's resources. The \nJSON **must** contain the configuration for the guest kernel and rootfs, as these \nare mandatory, but all of the other resources are optional, so it's your choice \nif you want to configure them or not. Because using this configuration method will \nalso start the microVM, you need to specify all desired pre-boot configurable resources \nin that JSON. The names of the resources are the ones from the `firecracker.yaml` file \nand the names of their fields are the same that are used in API requests. \nYou can find an example of configuration file at `tests/framework/vm_config.json`. \nAfter the machine is booted, you can still use the socket to send API requests\nfor post-boot operations.\n\n### Install firectl tool\n\n#### Install latest go on ubuntu\n\nInstall via snap:\n\n    apt install snapd\n    snap install go --classic\n\nIn ~/.bashrc:\n\n    export PATH=\"$PATH:/snap/bin\"\n    export GOPATH=\"/home/pmieden/go\"\n    export GOBIN=\"$GOPATH/bin\"\n    export PATH=\"$PATH:$GOBIN:$HOME/.cargo/bin\"\n\nReload\n\n    source ~/.bashrc\n\nFirectl:\n\n    go get github.com/firecracker-microvm/firectl\n\nfails with several errors. Go into the directory and install manually using go modules:\n\n    github.com/firecracker-microvm/firectl:$ go install\n\n### Create Disk Image\n\n    qemu-img create -f qcow2 file.qcow2 100M\n    mkfs.ext4 file.qcow2\n    mount file.qcow2 /mnt\n    ...\n    umount /mnt\n\n### StartVM with firectl\n\nStartVM:\n\n    firectl \\\n    --kernel=/tmp/hello-vmlinux.bin \\\n    --root-drive=/tmp/hello-rootfs.ext4 \\\n    --kernel-opts=\"console=ttyS0 noapic reboot=k panic=1 pci=off nomodules rw\" \\\n    --add-drive=file.qcow2:rw\n\nor\n\n    ./firectl \\\n    --kernel=hello-vmlinux.bin \\\n    --root-drive=hello-rootfs.ext4 \\\n    --add-drive=file.qcow2:rw\n\n### Mount disk image\n\n    fdisk -l\n    mount /dev/vdb /mnt\n\n### Mount Volume and Network Setup\n\nSee: https://medium.com/@s8sg/quick-start-with-firecracker-and-firectl-in-ubuntu-f58aeedae04b\n\n### Deploy Go Executable in AWS Lambda\n\nDocumentation: https://docs.aws.amazon.com/lambda/latest/dg/lambda-go-how-to-create-deployment-package.html\n\nDownload the Lambda library for Go with go get, and compile your executable.\n\n    ~/my-function$ go get github.com/aws/aws-lambda-go/lambda\n    ~/my-function$ GOOS=linux go build main.go\n\nCreate a deployment package by packaging the executable in a ZIP file, and use the AWS CLI to create a function. The handler parameter must match the name of the executable containing your handler.\n\n\n    ~/my-function$ zip function.zip main\n    ~/my-function$ aws lambda create-function --function-name my-function --runtime go1.x \\\n    --zip-file fileb://function.zip --handler main \\\n    --role arn:aws:iam::123456789012:role/execution_role\n\nInstall aws tools:\n\n    brew install awscli\n    aws configure\n\nFind role name in AWS Identity and Access Management (IAM) and query API:\n\n    dreadbook:websrv alien$ aws iam get-role --role-name test-role-ct1y0gwd\n    {\n        \"Role\": {\n            \"Path\": \"/service-role/\",\n            \"RoleName\": \"test-role-ct1y0gwd\",\n            \"RoleId\": \"AROA5NS7SA6O5UEFKEZGH\",\n            \"Arn\": \"arn:aws:iam::922544637853:role/service-role/test-role-ct1y0gwd\",\n            \"CreateDate\": \"2019-11-14T16:49:14Z\",\n            \"AssumeRolePolicyDocument\": {\n                \"Version\": \"2012-10-17\",\n                \"Statement\": [\n                    {\n                        \"Effect\": \"Allow\",\n                        \"Principal\": {\n                            \"Service\": \"lambda.amazonaws.com\"\n                        },\n                        \"Action\": \"sts:AssumeRole\"\n                    }\n                ]\n            },\n            \"MaxSessionDuration\": 3600\n        }\n    }\n\nDeploy:\n\n    dreadbook:websrv alien$ aws lambda create-function --function-name my-function --runtime go1.x   --zip-file fileb://function.zip --handler main   --role arn:aws:iam::922544637853:role/service-role/test-role-ct1y0gwd\n    {\n        \"FunctionName\": \"my-function\",\n        \"FunctionArn\": \"arn:aws:lambda:eu-west-1:922544637853:function:my-function\",\n        \"Runtime\": \"go1.x\",\n        \"Role\": \"arn:aws:iam::922544637853:role/service-role/test-role-ct1y0gwd\",\n        \"Handler\": \"main\",\n        \"CodeSize\": 3821143,\n        \"Description\": \"\",\n        \"Timeout\": 3,\n        \"MemorySize\": 128,\n        \"LastModified\": \"2019-11-14T20:18:39.549+0000\",\n        \"CodeSha256\": \"lzi65uyX7IbnW/S0xWrydlmuEKDQ7Dzg8h10i0dwGOg=\",\n        \"Version\": \"$LATEST\",\n        \"TracingConfig\": {\n            \"Mode\": \"PassThrough\"\n        },\n        \"RevisionId\": \"d4bc2377-7930-499a-8c46-6740b24ca9f2\"\n    }\n\n\u003e Create an API Gateway in Lambda Console.\n\nInvoke:\n\n    aws lambda invoke --function-name hello --payload '{ \"key\": \"value\" }' response.json\n\n\n### Custom RootFS for experiments\n\n#### Compile websrv on ubuntu host\n\n    apt install musl-tools\n    root@oslo:~/go/src/github.com/dreadl0ck/os3/ls/websrv# CC=musl-gcc go build --ldflags '-linkmode external -extldflags \"-static\"'\n\n#### Setup FS\n\nSource: https://github.com/firecracker-microvm/firecracker/blob/master/docs/rootfs-and-kernel-setup.md\n\n- create_rootfs.sh (outside)\n- init_alpine.sh (run inside container):\n\nHint: You can also copy the binary from the outside into the container:\n\n    docker cp ~/go/src/github.com/dreadl0ck/os3/ls/websrv/websrv $(docker ps -q --filter ancestor=alpine):/my-rootfs/usr/bin\n\nUmount on server:\n    \n    sync\n    umount /tmp/my-rootfs\n\nYou should now have a kernel image (vmlinux) and a rootfs image (rootfs.ext4), that you can boot with Firecracker.\n\n\n### IP space\n\nAlpine Network setup: https://wiki.alpinelinux.org/wiki/Configure_Networking\n\nhttps://github.com/firecracker-microvm/firecracker/blob/master/docs/network-setup.md\n\n    Address:   145.100.106.16        10010001.01100100.01101010.0001 0000\n    Netmask:   255.255.255.240 = 28  11111111.11111111.11111111.1111 0000\n    Wildcard:  0.0.0.15              00000000.00000000.00000000.0000 1111\n    =\u003e\n    Network:   145.100.106.16/28     10010001.01100100.01101010.0001 0000 (Class B)\n    Broadcast: 145.100.106.31        10010001.01100100.01101010.0001 1111\n    HostMin:   145.100.106.17        10010001.01100100.01101010.0001 0001\n    HostMax:   145.100.106.30        10010001.01100100.01101010.0001 1110\n    Hosts/Net: 14\n    \n#### Run Firecracker Unit Tests\n\n    cd firecracker\n    tools/devtool test 2\u003e\u00261 \u003e firecracker_tests.log \n\n#### Run Rust Linter\n\n    rustup target add x86_64-unknown-linux-musl\n    cargo clippy\n    ...\n    \n### Automate microVM start\n    \n    dreadl0ck\n    cd microbench\n    cli/create_rootfs.sh \u0026\u0026 bin/microbench 145.100.106.18\n\n### Benchmark kernel boot time\n\nParse */var/log/boot.msg* or */var/log/kern.log* for information regarding kernel boot time.\n\nSee: https://unix.stackexchange.com/questions/500732/how-to-find-out-time-taken-by-linux-system-for-cold-boot\n\nThose do not seem to be present in alpine.\n\nCheck *cat /proc/uptime* and *dmesg* output.\n\nAlternatively:\n\n- https://wiki.archlinux.org/index.php/Bootchart\n- http://people.redhat.com/berrange/systemtap/bootprobe/\n\nWhat values are we interested in?\n\n- Kernel boot time (via kernel logs)\n- Service startup time (via kernel logs)\n- Network stack reachability (via ping from outside)\n- Time until reachability of a static webservice (via HTTP GET from outside)\n\n### Firecracker Linter Output\n\n- 9x warning: unsafe function's docs miss `# Safety` (all in memory_model)\n- 1x deprecated symbol used (in devices)\n\n### Firecracker Test Output\n\nWhat security aspects are tested?\n\n- seccomp\n- sec_audit\n- jailing\n\nSearch test logs:\n\n    $ grep \"security\" logs/firecracker_tests.log\n    integration_tests/security/test_jail.py ..\n    integration_tests/security/test_sec_audit.py .\n    integration_tests/security/test_seccomp.py .Hello, world!\n    5.99s setup    integration_tests/security/test_seccomp.py::test_seccomp_ls\n    1.29s call     integration_tests/security/test_sec_audit.py::test_cargo_audit\n    1.26s teardown integration_tests/security/test_seccomp.py::test_seccomp_applies_to_all_threads[ubuntu]\n    0.55s setup    integration_tests/security/test_jail.py::test_default_chroot[ubuntu_with_ssh]\n    0.54s setup    integration_tests/security/test_jail.py::test_empty_jailer_id[ubuntu_with_ssh]\n    0.29s call     integration_tests/security/test_jail.py::test_default_chroot[ubuntu_with_ssh]\n    0.19s call     integration_tests/security/test_seccomp.py::test_seccomp_applies_to_all_threads[ubuntu]\n    0.09s setup    integration_tests/security/test_seccomp.py::test_seccomp_applies_to_all_threads[ubuntu]\n    0.07s teardown integration_tests/security/test_jail.py::test_default_chroot[ubuntu_with_ssh]\n    0.07s call     integration_tests/security/test_jail.py::test_empty_jailer_id[ubuntu_with_ssh]\n    0.07s teardown integration_tests/security/test_jail.py::test_empty_jailer_id[ubuntu_with_ssh]\n    0.01s call     integration_tests/security/test_seccomp.py::test_seccomp_ls\n\nPerformance measurements:\n\n    $ grep \"performance\" logs/firecracker_tests.log\n    integration_tests/performance/test_boottime.py FFFF\n    integration_tests/performance/test_process_startup_time.py Process startup time is: 23428 us (6601 CPU us)\n    integration_tests/performance/test_boottime.py:30: in test_single_microvm_boottime_no_network\n    integration_tests/performance/test_boottime.py:98: in _test_microvm_boottime\n    integration_tests/performance/test_boottime.py:46: in test_multiple_microvm_boottime_no_network\n    integration_tests/performance/test_boottime.py:98: in _test_microvm_boottime\n    integration_tests/performance/test_boottime.py:62: in test_multiple_microvm_boottime_with_network\n    integration_tests/performance/test_boottime.py:138: in _configure_vm\n    integration_tests/performance/test_boottime.py:80: in test_single_microvm_boottime_with_network\n    integration_tests/performance/test_boottime.py:98: in _test_microvm_boottime\n    3.99s call     integration_tests/performance/test_boottime.py::test_multiple_microvm_boottime_no_network[minimal, 10 instance(s)]\n    2.95s call     integration_tests/performance/test_boottime.py::test_multiple_microvm_boottime_with_network[minimal, 10 instance(s)]\n    0.81s call     integration_tests/performance/test_boottime.py::test_single_microvm_boottime_with_network[minimal]\n    0.64s call     integration_tests/performance/test_boottime.py::test_single_microvm_boottime_no_network[minimal]\n    0.57s call     integration_tests/performance/test_process_startup_time.py::test_startup_time[ubuntu]\n    0.12s setup    integration_tests/performance/test_boottime.py::test_multiple_microvm_boottime_with_network[minimal, 10 instance(s)]\n    0.12s setup    integration_tests/performance/test_boottime.py::test_multiple_microvm_boottime_no_network[minimal, 10 instance(s)]\n    0.11s setup    integration_tests/performance/test_boottime.py::test_single_microvm_boottime_with_network[minimal]\n    0.11s setup    integration_tests/performance/test_boottime.py::test_single_microvm_boottime_no_network[minimal]\n    0.10s setup    integration_tests/performance/test_process_startup_time.py::test_startup_time[ubuntu]\n    0.05s teardown integration_tests/performance/test_boottime.py::test_multiple_microvm_boottime_no_network[minimal, 10 instance(s)]\n    0.03s teardown integration_tests/performance/test_boottime.py::test_multiple_microvm_boottime_with_network[minimal, 10 instance(s)]\n    0.01s teardown integration_tests/performance/test_boottime.py::test_single_microvm_boottime_no_network[minimal]\n    0.01s teardown integration_tests/performance/test_process_startup_time.py::test_startup_time[ubuntu]\n    0.01s teardown integration_tests/performance/test_boottime.py::test_single_microvm_boottime_with_network[minimal]\n\n- integration_tests/performance/test_process_startup_time.py Process startup time is: 23428 us (6601 CPU us)\n- Total: 5 failed, 64 passed, 1 skipped in 946.56s (0:15:46)\n\n## QEMU\n\nInspired by [firecracker's microvms](https://github.com/firecracker-microvm/firecracker/blob/master/docs/design.md), QEMU released [support for microvms](https://github.com/qemu/qemu/blob/master/docs/microvm.rst)\n\n## Prerequisites\n\n```bash\nsudo apt install qemu qemu-kvm\n```\n\n### Shellcheck\nInstall [shellcheck](https://github.com/koalaman/shellcheck) and run it as a pre-commit hook e.g. `cp hooks/pre-commit .git/hooks/`\n\n```bash\nsudo apt install shellcheck\ncp hooks/pre-commit .git/hooks/pre-commit\n```\n\n### Qemu installation\n\nThe ubuntu package manager only has qemu version 2.11. Since support for microvms is in the latest version (4.20) we are going to have to build QEMU from source.\n\n```bash\n# update sources list\nsudo cp /etc/apt/sources.list /etc/apt/sources.list~\nsudo sed -Ei 's/^# deb-src /deb-src /' /etc/apt/sources.list\nsudo apt update\n\n# install qemu dependencies \u0026 build tools\nsudo apt build-dep qemu\nsudo apt install build-essential\n\n# install qemu from source\nwget https://download.qemu.org/qemu-4.2.0-rc2.tar.xz\ntar xvJf qemu-4.2.0-rc2.tar.xz\ncd qemu-4.2.0-rc2\n./configure\nmake\nsudo make install\n```\n\n### Linux kernel compilation\nhttps://github.com/firecracker-microvm/firecracker/blob/master/docs/rootfs-and-kernel-setup.md\n```bash\n# get linux source code\ngit clone https://github.com/torvalds/linux.git linux.git\ncd linux.git\n\n# checkout the version you want\ngit checkout v5.3\n\n# get microvm custom kernel\ngit clone https://gist.github.com/ppartarr/0f501d22788ad7ca214472814f3a87a1 .config\n\n# build uncompressed kernel image\nmake -j32 vmlinux\n```\n\n### Alpine rootfs\nCreate a minimal alpine rootfs for QEMU\n```bash\nwget http://dl-cdn.alpinelinux.org/alpine/v3.10/releases/x86_64/alpine-minirootfs-3.10.2-x86_64.tar.gz\nqemu-img create -f raw alpine-rootfs-x86_64.raw 1G\nsudo losetup /dev/loop0 alpine-rootfs-x86_64.raw\nsudo mkfs.ext4 /dev/loop0\nsudo mount /dev/loop0 /mnt\nsudo tar xpf alpine-minirootfs-3.10.2-x86_64.tar.gz -C /mnt\nsudo umount /mnt\nsudo losetup -d /dev/loop0\n```\n\n## Running a microvm\n\nSee early boot logs with legacy console:\n```bash\nsudo qemu-system-x86_64 \\\n  -M microvm \\\n  -enable-kvm \\\n  -smp 2 \\\n  -m 1g \\\n  -kernel vmlinux-microvm \\\n  -append \"earlyprintk=ttyS0 console=ttyS0 root=/dev/vda init=/bin/sh\" \\\n  -nodefaults \\\n  -no-user-config \\\n  -nographic \\\n  -serial stdio \\\n  -drive id=test,file=alpine/alpine-rootfs-x86_64.raw,format=raw,if=none \\\n  -device virtio-blk-device,drive=test \\\n  -netdev tap,id=tap0,script=no,downscript=no \\\n  -device virtio-net-device,netdev=tap0 \\\n  -no-reboot\n```\n\n```bash\nsudo qemu-system-x86_64 \\\n  -M microvm \\\n  -enable-kvm \\\n  -smp 2 \\\n  -m 1g \\\n  -kernel vmlinux-redhat \\\n  -append \"console=hvc0 root=/dev/vda init=/bin/sh rootfstype=ext4\" \\\n  -nodefaults \\\n  -no-user-config \\\n  -nographic \\\n  -serial pty \\\n  -chardev stdio,id=virtiocon0,server \\\n  -device virtio-serial-device \\\n  -device virtconsole,chardev=virtiocon0 \\\n  -netdev user,id=testnet \\\n  -device virtio-net-device,netdev=testnet \\\n  -drive id=test,file=alpine/alpine-rootfs-x86_64.raw,format=raw,if=none \\\n  -device virtio-blk-device,drive=test \\\n  -no-reboot\n```\n\n### FAQ\n\n**Q: why do I get the following error?**\n```bash\nqemu-system-x86_64: error: failed to set MSR 0x480 to 0x0\nqemu-system-x86_64: /opt/qemu-4.2.0-rc1/target/i386/kvm.c:2932: kvm_put_msrs: Assertion `ret == cpu-\u003ekvm_msr_buf-\u003enmsrs' failed.\nAborted\n```\n\n**Q: how do I connect to a serial console i.e. ttyS0**\nRun qemu with a legacy console: `-append \"console=9600,ttyS0\"` and connect with minicom\n```bash\nminicom -D /dev/ttyS0 -b 9600\n```\n\n**Q: Why do I receive a QEMU KVM Permission Denied Error?**\n\n    Could not access KVM kernel module: Permission denied\n    qemu-system-x86_64: failed to initialize kvm: Permission denied\n\nFor the jailing to work, update the permissions and add the jail_user to the _kvm_ group: \n\n    # chown root:kvm /dev/kvm\n    # chmod 666 /dev/kvm\n    # usermod -a -G kvm \u003cjail_user\u003e\n    # addgroup libvirtd\n    # usermod -a -G libvirtd \u003cjail_user\u003e\n    # systemctl restart libvirtd.service\n    \nAlso make sure the kernel file is owned by the jail_user:\n\n    # chown \u003cjail_user\u003e \u003cpath/to/vmlinuz\u003e\n\nVerify access works as jail user:\n\n    $ kvm-ok\n    INFO: /dev/kvm exists\n    KVM acceleration can be used\n    \nCheck group ownerships of jail_user:\n\n    $ id  \n    uid=1000(jail_user) gid=1000(jail_user) groups=1000(jail_user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),111(lpadmin),112(sambashare),113(docker),114(kvm),116(libvirt),1003(libvirtd)\n    \nTo Persist changes to /dev/kvm between reboots,\ncreate a file _/lib/udev/rules.d/99-kvm.rules_ with this content:\n\n    KERNEL==\"kvm\", GROUP=\"kvm\", MODE=\"0666\"","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdreadl0ck%2Fmicrobench","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdreadl0ck%2Fmicrobench","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdreadl0ck%2Fmicrobench/lists"}