{"id":18869885,"url":"https://github.com/eyalz800/zpp_hypervisor","last_synced_at":"2026-03-08T09:31:44.512Z","repository":{"id":44546225,"uuid":"184153266","full_name":"eyalz800/zpp_hypervisor","owner":"eyalz800","description":"A very simple hypervisor for learning experience.","archived":false,"fork":false,"pushed_at":"2021-10-25T22:52:07.000Z","size":127,"stargazers_count":127,"open_issues_count":2,"forks_count":29,"subscribers_count":9,"default_branch":"master","last_synced_at":"2024-06-05T13:43:45.915Z","etag":null,"topics":["hypervisor"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eyalz800.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-04-29T22:32:01.000Z","updated_at":"2024-05-12T16:44:31.000Z","dependencies_parsed_at":"2022-08-01T01:18:03.808Z","dependency_job_id":null,"html_url":"https://github.com/eyalz800/zpp_hypervisor","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eyalz800%2Fzpp_hypervisor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eyalz800%2Fzpp_hypervisor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eyalz800%2Fzpp_hypervisor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eyalz800%2Fzpp_hypervisor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eyalz800","download_url":"https://codeload.github.com/eyalz800/zpp_hypervisor/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223634418,"owners_count":17176960,"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":["hypervisor"],"created_at":"2024-11-08T05:18:02.795Z","updated_at":"2026-03-08T09:31:44.464Z","avatar_url":"https://github.com/eyalz800.png","language":"C++","readme":"zpp_hypervisor\n==============\n[![Build Status](https://dev.azure.com/eyalz800/zpp_hypervisor/_apis/build/status/eyalz800.zpp_hypervisor?branchName=master)](https://dev.azure.com/eyalz800/zpp_hypervisor/_build/latest?definitionId=1\u0026branchName=master)\n[![Build Status](https://travis-ci.org/eyalz800/zpp_hypervisor.svg?branch=master)](https://travis-ci.org/eyalz800/zpp_hypervisor)\n[![Build status](https://ci.appveyor.com/api/projects/status/wi0kttdsy3v7jd3d/branch/master?svg=true)](https://ci.appveyor.com/project/eyalz800/zpp-hypervisor/branch/master)\n\nA very simple hypervisor for learning experience.\n\nAbstract\n--------\nThis project is really about playing with intel hardware virtualization features, which for me helps understanding\nhow they work.\n\nMotivation\n----------\nCreate a hypervisor project such that:\n1. It can be debugged easily in source mode.\n2. Really simple and fast build.\n3. OS independent except for a few wrapper functions during the load inside a driver code\nthat has to be written for every OS.\n4. Works in UEFI.\n\nProject Overview\n----------------\nThe project consists of several parts:\n1. hypervisor.\n2. Linux loader driver.\n3. Windows loader driver.\n4. UEFI loader application.\n\nThe hypervisor is a self contained ELF binary that aims to be cross platform.\nThe Linux / Windows / UEFI loader drivers are there to load the hypervisor\nunder Linux, Windows, and UEFI respectively.\n\nProject Configuration\n---------------------\nThe project is configured using the `environment.config` file located at the project root.\nThis file configures important makefile variables for compiling and debugging environment.\nExample:\n```make\n# The supported architectures.\nSUPPORTED_ARCHITECTURES := x86_64\n\n# Selected architecture to build.\nSELECTED_ARCHITECTURE := x86_64\n\n# For SSH deployment, the SSH target, port, and password.\nSSH_TARGET := user@192.168.171.136\nSSH_PORT := 22\nSSH_PASSWORD := password1\n\n# For GDB debugging, the GDB server address.\nGDB_SERVER_ADDRESS := :1337\n\n# The drivers to build, linux, windows, uefi and both.\nBUILD_DRIVERS := linux windows uefi\n\n# Whether the hypervisor is configured to wait for debugger.\nHYPERVISOR_WAIT_FOR_DEBUGGER := 0\n\n# The linux kernel version for the linux driver.\nLINUX_KERNEL := 4.18.0-15-generic\n\n# Windows build dependencies can be referenced from either\n# the windows side, WSL, or an arbitrary linux machine with\n# access to the needed resources below.\nROOT :=\nifeq ($(OS), Windows_NT)\nROOT := C:\nelse\nROOT := /mnt/c\nendif\n\n# Windows build dependencies.\nVISUAL_STUDIO_ROOT := $(ROOT)/Program\\ Files\\ \\(x86\\)/Microsoft\\ Visual\\ Studio/2017/Community/VC/Tools/MSVC/14.16.27023\nWINDOWS_KITS_ROOT := $(ROOT)/Program\\ Files\\ \\(x86\\)/Windows\\ Kits/10\nWINDOWS_KITS_VERSION := 10.0.18362.0\nEDK2_ROOT := $(ROOT)/Temp/edk2-UDK2018\nANDROID_NDK_ROOT := $(ROOT)/CustomPrograms/android-ndk-r19b\nLLVM_ROOT := $(ROOT)/Program\\ Files/LLVM\n```\n\nCompiling The Project\n---------------------\nThis section describes what is needed to compile the project\nand its subprojects.\n\nThe list of requirements varies between the host system that is used for\nthe build and the loader drivers that are participating in the build.\n\n### Windows non-WSL:\nDownload / Install:\n1. [Android NDK](https://developer.android.com/ndk/downloads) to build the Hypervisor.\n2. [LLVM Releases](http://releases.llvm.org/download.html) to build the Windows and UEFI drivers.\n3. [Windows SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk) to build the Windows and UEFI drivers.\n4. [Windows WDK](https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk) to build the Windows and UEFI drivers.\n5. [Tianocore EDK2](https://github.com/tianocore/edk2) - to build UEFI driver.\n6. [Visual Studio Community](https://visualstudio.microsoft.com/vs/community) - for C/C++ headers use in Windows and UEFI drivers.\n7. [Git](https://git-scm.com/downloads) - for use of Linux commands located in the `/usr/bin` subfolder.\n\n- Make sure the WDK and SDK versions are the same.\n- Use `$(ANDROID_NDK_ROOT)/prebuilt/windows-x86_64/bin/make.exe` for compilation.\n- Prior to the build, set the PATH environment variable to have `C:/Program Files/Git/usr/bin` as first directory.\n- After finishing, proceed to the environment settings part below.\n\n### Linux / Windows WSL\nDownload / Install:\n1. Following packages:\n    * git\n    * make\n    * clang-7 or higher\n    * clang++-7 or higher\n    * lld-7 or higher\n    * libc++-7-dev or higher\n    * build-essential\n    * libelf-dev\n    * linux-headers-$(LINUX_KERNEL) where $(LINUX_KERNEL) is whatever version we want to build the Linux driver for,\n      typically $(uname -r) for non Windows machines.\n    * python, for generation of compile commands\n2. [Windows SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk) to build the Windows and UEFI drivers.\n3. [Windows WDK](https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk) to build the Windows and UEFI drivers.\n5. [Tianocore EDK2](https://github.com/tianocore/edk2) - to build UEFI driver.\n5. [Visual Studio Community](https://visualstudio.microsoft.com/vs/community) - for C/C++ headers use in Windows and UEFI drivers.\n\nNotes:\n- Make sure clang and clang++ point to the correct clang and clang++ versions.\n- Installing the Windows SDK, WDK as well as Visual Studio is meant to be done\nin a windows machine. The intention is to either copy the Visual Studio headers and the SDK,\nWDK to the Linux machine or use a shared folder.\n- After finishing, proceed to the environment settings part below.\n\n### Environment Settings (Shared)\nMake sure the `./environment.config` file contains your correct paths and settings in\nyour environment:\n1. Adjust the `BUILD_DRIVERS` configuration to build Linux/Windows/UEFI drivers or both.\nTo compile just the hypervisor, leave `BUILD_DRIVERS` empty.\n2. Change `HYPERVISOR_WAIT_FOR_DEBUGGER` to whether or not you wish the hypervisor to\nwait for debugging.\n3. For Linux driver build:\n    * Adjust the `LINUX_KERNEL` variable to control linux headers version.\n    * Note: under Windows this must use WSL.\n4. For Windows driver build:\n    * Adjust the `VISUAL_STUDIO_ROOT`, `WINDOWS_KITS_ROOT`, and `WINDOWS_KITS_VERSION` accordingly.\n    * Note: Supports Linux machines as well as WSL, as long as those paths are accessible.\n5. For UEFI driver build:\n    * In case you are building the UEFI driver, adjust the `EDK2_ROOT` field to the EDK2 directory.\n    * Make sure all requirements for Windows driver build are met.\n6. For Windows non-WSL build, adjust the `LLVM_ROOT` and `ANDROID_NDK_ROOT` to the LLVM installation\nfolder and `ANDROID_NDK_ROOT` folder respectively.\n\n### Compilation Command\nAfter completing the above steps, just run `make -j` or `make -j mode=release` for to build the\nproject for debug or release configuration respectively.\n\nThe build output will be located at the `./out` folder.\n\nLoading The Hypervisor\n----------------------\n\n### Linux\nTo load the hypervisor on a remote Linux machine, use the `./environment/linux_load.sh` script that will\npush the loader driver which has the hypervisor binary within and run it.\n\nThe loader driver will load the hypervisor and exit immediately afterwards, due to an intentional\nerror code return to the Linux kernel, the error code is EPERM.\n\nNote: The `./environment/linux_load.sh` script requires `sshpass` to avoid having to type the password in SSH,\ntherefore it needs to be installed.\n\n### Windows\nThere is currently no script that automatically loads the hypervisor for Windows, thus, we have\nto load the driver manually.\n\nTo load the hypervisor on a Windows machine, move the driver located at `./out/debug/x86_64/zpp_loader.sys`\nto the machine and load the driver using:\n```sh\n\u003e sc create zpp_loader type=kernel binPath=C:/path/to/zpp_loader.sys\n\u003e sc start zpp_loader\n```\n\nRemember to turn off integrity checks beforehand.\n\nThe windows driver returns an error code of `STATUS_INSUFFICIENT_POWER` when it succeeds, to unload itself.\n\n### UEFI\nI am yet to be familiar with UEFI best practices. Until now I have used a rather violant\nmount of the EFI partition and replaced the `*.efi` image that I knew was the main boot selection.\n\nCurrently the UEFI support is really experimental, there are probably many issues that are invisible to me,\nsome are multi core issues that I did not handle and yet to even have the knowlege to solve.\nI am planning to learn more about those issues and solve them eventually.\n\nDebugging The Project\n---------------------\nDebugging the project can be done using `gdb` together with VMWare or Qemu-KVM that are configured\nto allow nested virtualization and expose a `gdb stub`.\n\nA friendly reminder for `Visual Studio` users in Windows, is that it supports connecting to a `gdb stub` allowing\npretty much the same debugging experience as any other application compiled in `Visual Studio`.\n\nThe hypervisor can be configured using the `environment.config` file to perform a busy loop until\na debugger is attached and changes the loop variable `gdb_attached`, make sure to enable this and compile the\n`./hypervisor/src/hypervisor/main.cpp` file again to enjoy the refreshed setting.\n\nWhile the hypervisor is inside the busy loop, we typically have the instruction pointer within our module\nwhich makes it easy for our debugging scripts to find the module base and load symbol information, as well\nas getting out of the loop by changing the loop variable.\n\n### Configuring VMWare for Debugging\n1. In your VMware processor configuration, enable 'Virtualize Intel VT-x/EPT or AMD-V/RVI'.\n2. Add the following lines to the VMWare `.vmx` file:\n```py\ndebugStub.listen.guest64.remote = \"TRUE\"\ndebugStub.port.guest64 = \"1337\"\ndebugStub.hideBreakpoints = \"TRUE\"\nmonitor.debugOnStartGuest64 = \"TRUE\"\n```\nI recommend using the `hideBreakpoints` configuration listed above,\nwhich makes gdb uses hardware breakpoints instead of patching the code which has lead me to unpleasant pitfalls.\nThis configurtion however limits the amount of breakpoints to four, use wisely.\nIn addition, I recommend using the `debugOnStartGuest64` configuration listed above as well as it waits for you to attach to the VM before starting\nto use it.\nWhen you build the project, a directory named `environment` will be created according to this configuration with\nuseful environmental scripts.\n\n### Configuring Qemu-KVM for Debugging\nThis is fairly simple, just add the following option to the qemu-kvm launch command line:\n```sh\n-gdb tcp::1337\n```\n\n### Configuring regular Linux GDB for Debugging\nOnce having the debug machine ready and waiting for connection, run the following command from the root\ndirectory of the project:\n```sh\ngdb --command=./environment/gdbcommand\n```\n\nOnce inside gdb, once your instruction pointer is within the hypervisor, use the `zstartl` command that was added\nto gdb in the command file given to it. This command will look for the ELF header of the hypervisor and load symbols.\n\n### Configuring Windows Visual Studio for Debugging\nOnce having the debug machine ready and waiting for connection, launch the command window of Visual Studio\nusing the Ctrl+Alt+A shortcut, and define the following alias:\n```\n\u003ealias d Debug.MIDebugLaunch /Executable:C:/ /OptionsFile:C:/Projects/git/zpp_hypervisor/environment/options.xml\n```\nThis alias will be used to attach to the target machine `gdb` interface.\nNotice that the executable switch to the command is not used so it is safe to leave it as `C:/`, as for the `OptionsFile`, remember\nto provide a full path to the `options.xml` file inside the `environment/options.xml` located at the project root.\n\nAlso, I recommend defining the following alias to easily execue `gdb` commands within `Visual Studio`:\n```\n\u003ealias e Debug.MIDebugExec\n```\n\nNow, to attach to the target machine, execute the following command within the command window:\n```\n\u003ed\n```\n\nTo load symbols once the instruction pointer is within the hypervisor, execute the following command\nin the command window:\n```\n\u003ee zstartw\n```\n\nFinal Words\n-----------\nI hope that you enjoy using this project and feel free to report any issues.\n\n","funding_links":[],"categories":["Research Projects"],"sub_categories":["AMD"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feyalz800%2Fzpp_hypervisor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feyalz800%2Fzpp_hypervisor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feyalz800%2Fzpp_hypervisor/lists"}